home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
CRS
/
crs49.d81
/
hack6b.sfx
/
issue6b
Wrap
Text File
|
1990-02-12
|
58KB
|
1,607 lines
=============================================================================
╠┌╫ ├OMPRESSION
BY ┬ILL ╠UCIER (┬LUCIER@ERSYS.EDMONTON.AB.CA, B.LUCIER1 ON ╟ENIE)
╠┌╫ IS PERHAPS THE MOST WIDELY USED FORM OF DATA COMPRESSION TODAY. ╔T
IS SIMPLE TO IMPLEMENT AND ACHIEVES VERY DECENT COMPRESSION AT A FAIRLY
QUICK PACE. ╠┌╫ IS USED IN ╨╦┌╔╨ (SHRINK),╨╦┴╥├ (CRUNCH), GIFS,╓.42BIS
AND UNIX'S COMPRESS. ╘HIS ARTICLE WILL ATTEMPT TO EXPLAIN HOW THE
COMPRESSION WORKS WITH A SHORT EXAMPLE AND 6502 SOURCE CODE IN ┬UDDY
FORMAT.
╧RIGINALLY NAMED LZ78, IT WAS INVENTED BY ╩ACOB ┌IV AND ┴BRAHAM ╠EMPEL
IN 1978 , IT WAS LATER MODIFIED BY ╘ERRY ╫ELCH TO ITS PRESENT FORMAT.
╘HE PATENT FOR THE ╠┌╫ COMPRESSION METHOD IS PRESENTLY HELD BY ╒NISYS.
╠┌╫ COMPRESSES DATA BY TAKING PHRASES AND COMPRESSING THEM INTO CODES.
╘HE SIZE OF THE CODES COULD VARY FROM 9 BITS TO 16 BITS. ┴LTHOUGH FOR
THIS IMPLEMENTATION WE WILL BE USING ONLY 12 BITS. ┴S BYTE ARE READ IN
FROM A FILE THEY ARE ADDED TO A DICTIONARY. ╞OR A 12-BIT IMPLEMENTATION
A DICTIONARY WILL BE 4K (2^12=4096) . ┼ACH ENTRY IN THE DICTIONARY
REQUIRES FIVE BYTES, WHICH WILL BE BUILT IN THE FORM OF A TREE. ╔T IS
NOT A BINARY TREE BECAUSE EACH NODE MAY HAVE MORE THAN TWO OFFSPRINGS.
╔N FACT, BECAUSE OUR DICTIONARY CAN HOLD UP TO 4096 DIFFERENT CODES IT
IS POSSIBLE TO HAVE ONE NODE WITH 3800 CHILDREN NODES, ALTHOUGH THIS IS
NOT LIKELY TO HAPPEN. ╘HE FIVE BYTES THAT MAKE UP OUR TREE WILL BE:
╘HE PARENT CODE: ┼ACH NODE HAS ONE AND ONLY ONE PARENT NODE. ╫HEN THE PARENT
CODE IS LESS THEN 255 IT IS THE END OF A PHRASE. ╘HE CODES
0-255 DO NOT ACTUALLY EXIST IN THE TREE. ╘HE FOLLOWING
VALUES DO NOT APPEAR EITHER AS THEY HAVE SPECIAL MEANING:
256 : ┼ND OF ╙TREAM-╘HIS MARKS THE END OF ONE COMPRESSED FILE
257 : ╘HIS TELLS THE DECOMPRESSOR TO INCREASE THE NUMBER
OF BITS ITS READING BY ONE.
258 : ╫IPE OUT DICTIONARY
╘HE CODE VALUE : ╘HIS IS THE CODE THAT WILL BE SENT TO THE COMPRESSOR.
╘HE CHARACTER : ╘HE VALUE CONTAINED AT THIS NODE. ╔T HAVE A VALUE OF 0-255.
╔NITIALLY WE SEND OUT CODES THAT ARE 9 BITS LONG, THIS WILL COVER THE VALUES
0-511. ╧NCE WE HAVE REACHED 511, WE WILL NEED TO INCREASE THE NUMBER OF
BITS TO WRITE BY 1. ╘HIS WILL GIVE ROOM FOR CODE NUMBERS 512-1023, OR
(2^10)-1. ┴T THIS POINT WE MUST ENSURE THAT THE DECOMPRESSOR KNOWS HOW
BITS TO READ IN AT ONCE SO A CODE NUMBER 257 IS SENT TO INDICATE THAT
THE NUMBER OF BITS TO BE READ IS TO BE BUMPED UP BY ONE. ╘HE SIZE OF THE
DICTIONARY IS FINITE SO AT SOME POINT WE DO HAVE TO BE CONCERNED WITH
WHAT WE WILL DO WHEN IT DOES FILL UP. ╫E COULD STOP COMPILING NEW
PHRASES AND JUST COMPRESS WITH THE ONES THAT ARE ALREADY IN THE
DICTIONARY. ╘HIS IS NOT A VERY GOOD CHOICE, FILES TEND TO CHANGE
FREQUENTLY (EG. PROGRAM FILES AS THEY CHANGE FROM CODE TO DATA) SO
STICKING WITH THE SAME DICTIONARY WILL ACTUALLY INCREASE THE SIZE OF THE
FILE OR AT BEST, GIVE POOR COMPRESSION. ┴NOTHER CHOICE IS TO WIPE THE
DICTIONARY OUT AND START BUILDING NEW CODES AND PHRASES, OR WIPE OUT
SOME OF THE DICTIONARY LEAVING BEHIND ONLY THE NEWER CODES AND PHRASES.
╞OR THE SAKE OF SIMPLICITY THIS PROGRAM WILL JUST WIPE OUT THE
DICTIONARY WHEN IT BECOMES FULL.
╘O ILLUSTRATE HOW ╠┌╫ WORKS A SMALL PHRASE WILL BE COMPRESSED : HEHER.
╘O START THE FIRST TWO CHARACTERS WOULD BE READ IN. ╘HE ╚ WOULD BE
TREATED AS THE PARENT CODE AND ┼ BECOMES THE CHARACTER CODE. ┬Y MEANS OF
A HASHING ROUTINE (THE HASHING ROUTINE WILL BE EXPLAINED MORE FULLY IN
THE SOURCE CODE) THE LOCATION WHERE ╚┼ SHOULD BE IS LOCATED. ╙INCE WE
HAVE JUST BEGUN THERE WILL BE NOTHING THERE,SO THE PHRASE WILL BE ADDED
TO THE DICTIONARY. ╘HE CODES 0-258 ARE ALREADY TAKEN SO WE START USING
259 AS OUR FIRST CODE. ╘HE BINARY TREE WOULD LOOK SOMETHING LIKE THIS:
NODE # 72 - ╚
▄
NODE #3200 259 - ┼
╘HE NODE # FOR ┼ IS AN ARBITRARY ONE. ╘HE COMPRESSOR MAY NOT CHOOSE
THAT LOCATION, 3200 IS USED STRICTLY FOR DEMONSTRATION PURPOSES. ╙O AT
NODE #3200 THE VALUES WOULD BE:
╨ARENT CODE - 72
CODE VALUE - 259
CHARACTER - ┼
╘HE NODE #72 IS NOT ACTUALLY USED. ┴S SOON AS A VALUE LESS THAN 255 IS
FOUND IT IS ASSUMED TO BE THE ACTUAL VALUE. ╫E CAN'T COMPRESS THIS YET
SO THE VALUE 72 IS SENT TO THE OUTPUT FILE(REMEMBER THAT IT IS SENT IN 9
BITS). ╘HE ┼ THEN BECOMES THE PARENT CODE AND A NEW CHARACTER CODE ( ╚ )
IS READ IN. ┴FTER AGAIN SEARCHING THE DICTIONARY THE PHRASE ┼╚ IS NOT
FOUND. ╔T IS ADDED TO THE DICTIONARY AS CODE NUMBER 260. ╘HEN WE SEND
THE ┼ TO THE DISK AND ╚ BECOMES THE NEW PARENT CODE AND THE NEXT ┼
BECOMES THE NEW CHARACTER CODE. ┴FTER SEARCHING THE DICTIONARY WE FIND
THAT WE CAN COMPRESS ╚┼ INTO THE CODE 259,WE WANT TO COMPRESS AS MUCH AS
POSSIBLE INTO ONE CODE SO WE MAKE 259 THE PARENT CODE. ╘HERE MAY BE A
LONGER STRING THEN ╚┼ THAT CAN BE COMPRESSED. ╘HE ╥ IS READ IN AS THE
NEW CHARACTER CODE. ╘HE DICTIONARY IS SEARCHED FOR THE A 259 FOLLOWED A
╥, SINCE IT IS NOT FOUND IT IS ADDED TO THE DICTIOARY AND IT LOOKS LIKE
THIS:
NODE #72 - ╚ NODE #69 - ┼
▄ ▄
NODE #3200 259 - ┼ NODE #1600 260 - ╚
▄
NODE #1262 261 - ╥
╘HEN THE VALUE 259 IS SENT TO THE OUTPUT FILE (TO REPRESENT THE ╚┼) AND
SINCE THAT IS THE ┼╧╞ THE ╥ IS SENT AS WELL,AS WELL AS A 256 TO INDICATE
THE ┼╧╞ HAS BEEN REACHED.
─ECOMPRESSION IS EXTREMELY SIMPLE. ┴S LONG AS THE DECOMPRESSOR MAINTAINS
THE DICTIONARY AS THE COMPRESSOR DID, THERE WILL BE NO PROBLEMS,EXCEPT
FOR ONE PROBLEM THAT CAN BE HANDLED AS AN EXCEPTIONAL CASE. ┴LL OF THE
LITTLE DETAILS OF INCREASING THE NUMBER OF BITS TO READ, AND WHEN TO
FLUSH THE DICTIONARY ARE TAKEN CARE OF BY THE COMPRESSOR. ╙O IF THE
DICTIONARY WAS INCREASED TO 8K, THE COMPRESSOR WOULD HAVE TO BE SET UP
TO HANDLE A LARGER DICTIONARY, BUT THE DECOMPRESSOR ONLY DOES AS THE
COMPRESSED FILE TELLS IT TO AND WILL WORK WITH ANY SIZE DICTIONARY. ╘HE
ONLY PROBLEM WOULD BE THAT A LARGER DICTIONARY WILL CREEP INTO THE RAM
UNDER THE ROM OR POSSIBLY EVEN USE ALL AVAILABLE MEMORY, BUT ASSUMING
THAT THE RAM IS AVAILABLE THE DECOMPRESSOR WILL NOT CHANGE. ╘HE
DECOMPRESSOR WOULD START OUT READING 9 BITS AT A TIME, AND STARTS IT
FREE CODE AT 259 AS THE COMPRESSOR DID. ╘O USE THE ABOVE INPUT FROM THE
COMPRESSOR AS AN EXAMPLE, THE OUTPUT WAS:
72 - ╞OR THE ╞IRST ╚
69 - ╞OR THE ╞IRST ┼
259 - ╞OR THE ├OMPRESSED ╚┼
82 - ╞OR THE ╥
256 - ┼OF INDICATOR
╘O BEGIN DECOMPRESSING, TWO VALUES ARE NEEDED. ╘HE ╚ AND ┼ ARE READ IN,
(NOTE THEY WILL BOTH BE 9 BITS LONG). ┴S THEY ARE BOTH BELOW 256 THEY
ARE AT THE END OF THE STRING AND ARE SENT STRAIGHT TO THE OUTPUT FILE.
╘HE FIRST FREE CODE IS 259 SO THAT IS THE VALUE ASSIGNED TO THE PHRASE
╚┼. ╬OTE WHEN DECOMPRESSING THERE IS NO NEED FOR THE HASHING ROUTINE,
THE CODES ARE THE ABSOLUTE LOCATIONS IN THE DICTIONARY (I.E. ╔F THE
DICTIONARY WAS CONSIDERED TO BE AN ARRAY THEN THE ENTRY NUMBER 259 WOULD
BE DICTIONARY[259]), BECAUSE OF THIS, THE CODE VALUE IS NO LONGER
NEEDED. ╙O THE DECOMPRESSOR WOULD HAVE AN ENTRY THAT LOOKS LIKE THIS:
╬ODE # 259
╨ARENT ├ODE - ╚
├HARACTER - ┼
╘HE DECOMPRESSOR WILL READ IN THE NEXT VALUE (259). ┬ECAUSE THE NODE
NUMBER IS AT THE END OF THE COMPRESSED STRING WE WILL HAVE TO TAKE THE
CODE VALUE AND PLACE IT ON A STACK, AND TAKE THEM OFF IN A
╠AST-IN,╞IRST-OUT (╠╔╞╧) FASHION. ╘HAT IS TO SAY THAT THE FIRST
CHARACTER TO GO ON THE STACK (IN THIS CASE THE ┼) WILL BE THE LAST TO
COME OFF. ╘HE SIZE OF THE STACK IS DEPENDENT ON THE SIZE OF THE
DICTIONARY, SO FOR THIS IMPLEMENTATION WE NEED A STACK THAT IS 4K LONG.
┴FTER ALL THE CHARACTERS FROM THE STRING HAVE BEEN PLACED ON THE STACK
THEY ARE TAKEN OFF AND SENT TO THE OUTPUTFILE.
╘HERE IS ONE SMALL ERROR THAT IS POSSIBLE WITH ╠┌╫ BECAUSE OF THE WAY
THE COMPRESSOR DEFINES STRINGS. ├ONSIDER THE COMPRESSION DICTIONARY THAT
HAS THE FOLLOWING IN IT:
NODE # ├ODE ╨ARENT CHARACTER
╓ALUE CODE
------ ------ ------ ---------
65 65 N/A ┴
723 259 65 ├
1262 260 259 ╒
2104 261 260 ╘
2506 262 261 ┼
╬OW IF THE COMPRESSOR WAS TO TRY TO COMPRESS THE STRING ┴├╒╘┼┴├╒╘┼┴ ╘HE
COMPRESSOR WILL FIND A MATCH FOR THE FIRST FIVE CHARACTERS '┴├╒╘┼' AND
WILL SEND A 262 TO THE OUTPUT FILE. ╘HEN IT WILL ADD THE FOLLOWING ENTRY
TO THE DICTIONARY:
3099 263 262 ┴
╬OW IT WILL TRY TO COMPRESS THE REMAINING CHARACTERS, AND IT FINDS THAT
IT CAN COMPRESS THE ENTIRE STRING WITH THE CODE 263, BUT NOTICE THAT THE
MIDDLE ┴, THE ONE THAT WAS JUST ADDED ONTO THE END OF THE STRING '┴├╒╘┼'
WAS NEVER SENT TO THE OUTPUT FILE. ╘HE DECOMPRESSOR WILL NOT HAVE THE
CODE 263 DEFINED IN IT'S DICTIONARY. ╘HE LAST CODE IT WILL HAVE DEFINED
WILL BE 262. ╘HIS PROBLEM IS EASILY REMEDIED THOUGH, WHEN THE
DECOMPRESSOR DOES NOT HAVE A CODE DEFINED, IT TAKES THE FIRST LETTER
FROM THE LAST PHRASE DEFINED AND TACKS IT ONTO THE END OF THE LAST
PHRASE. ╔┼ ╔T TAKES THE FIRST LETTER (THE ┴) FROM THE PHRASE AND ADDS IT
ON TO THE END AS CODE #263.
╘HIS PARTICULAR IMPLEMENTATION IS FAIRLY SLOW BECAUSE IT READS A BYTE
AND THEN WRITES ONE, IT COULD BE MADE MUCH FASTER WITH SOME BUFFERING.
╔T IS ALSO LIMITED TO COMPRESSING AND DECOMPRESSING ONE FILE AT A TIME
AND HAS NO ERROR CHECKING CAPABILITIES. ╔T IS MEANT STRICTLY TO TEACH
╠┌╫ COMPRESSION, NOT PROVIDE A FULL FLEDGED COMPRESSOR.
┴ND NOW FOR THE CODE:
╙┘╙ 4000 ; SYS 999 ON A 64
.─╓╧ 9 ; OR WHATEVER DRIVE USED FOR OUTPUT
.╧╥╟ 2500
.╧┬╩ "╠┌╫.═╠"
╘┴┬╠┼╙╔┌┼ =5021
; ╘╚┼ ╘┴┬╠┼╙╔┌┼ ╔╙ ┴├╘╒┴╠╠┘ 5021, ┴┬╧╒╘ 20% ╠┴╥╟┼╥ ╘╚┼╬ 4╦. ╘╚╔╙ ╟╔╓┼╙
; ╘╚┼ ╚┴╙╚╔╬╟ ╥╧╒╘╔╬┼ ╙╧═┼ ╥╧╧═ ╘╧ ═╧╓┼. ╔╞ ╘╚┼ ╘┴┬╠┼ ╫┴╙ ┼╪┴├╘╠┘ 4╦
; ╘╚┼╥┼ ╫╧╒╠─ ┬┼ ╞╥┼╤╒┼╬╘ ├╧╠╠╔╙╔╧╬╙ ╫╚┼╥┼ ─╔╞╞┼╥┼╬╘ ├╧═┬╔╬┴╘╔╧╬╙ ╧╞
; ├╚┴╥┴├╘┼╥╙ ╫╧╒╠─ ╚┴╓┼ ╘╚┼ ╙┴═┼ ╚┴╙╚ ┴──╥┼╙╙. ╔╬├╥┼┴╙╔╬╟ ╘╚┼ ╘┴┬╠┼ ╙╔┌┼
; ╥┼─╒├┼╙ ╘╚┼ ╬╒═┬┼╥ ╧╞ ├╧╠╠╔╙╔╧╬╙.
┼╧╙ =256 ; EOS = ┼ND OF STREAM ╘HIS MARKS THE END OF FILE
╞╔╥╙╘├╧─┼ =259
═┴╪├╧─┼ =4096
┬╒═╨├╧─┼ =257 ; ╫HENEVER A 257 IS ENCOUNTERED BY THE DECOMPRESSOR IT
; INCREASES THE NUMBER OF BITS IT READS BY 1
╞╠╒╙╚├╧─┼ =258
╘┴┬╠┼┬┴╙┼ =14336 ; ╘HE LOCATION THAT THE DICTIONARY IS LOCATED AT
─┼├╧─┼╙╘┴├╦ =9300 ; ╘HE LOCATION OF THE 4K ╠╔╞╧ STACK
; ╧╥╟ = ─┼├╧═╨╥┼╙╙ ╞╔╠┼
; ╧╥╟ + 3 = ├╧═╨╥┼╙╙ ╞╔╠┼
╩═╨ ┼╪╨┴╬─╞╔╠┼
;********************************
; ├╧═╨╥┼╙╙╞╔╠┼
;********************************
├╧═╨╥┼╙╙╞╔╠┼ ╩╙╥ ╔╬╔╘─╔├ ; ┼═╨╘┘ ╘╚┼ ─╔├╘╔╧╬┴╥┘
╠─┴ #128
╙╘┴ ┬╔╘═┴╙╦
╠─┴ #0
╙╘┴ ╥┴├╦
╩╙╥ ╟┼╘├╚┴╥ ; ╟┼╘ ┴ ├╚┴╥ ╞╥╧═ ╘╚┼ ╔╬╨╒╘ ╞╔╠┼
╙╘┴ ╙╘╥╔╬╟├╧─┼ ; ╔╬╔╘╔┴╠╔┌┼ ╘╚┼ ╙╘╥╔╬╟├╧─┼ (╨┴╥┼╬╘ ├╧─┼)
╠─┴ #0
╙╘┴ ╙╘╥╔╬╟├╧─┼+1
╬┼╪╘├╚┴╥ ╩╙╥ ╟┼╘├╚┴╥
╙╘┴ ├╚┴╥┴├╘┼╥
╩╙╥ ╞╔╬─╬╧─┼ ; ╞╔╬─╬╧─┼ ├┴╠├╒╠┴╘┼╙ ╘╚┼ ╚┴╙╚┼─ ╠╧├┴╘╔╧╬ ╧╞
╠─┴ ($╞┼),┘ ; ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥ ╔╬ ╘╚┼ ─╔├╘.
╔╬┘ ; ┴╬─ ╙┼╘╙ $╞┼/$╞╞ ╨╧╔╬╘╔╬╟ ╘╧ ╔╘. ╔╞ ╘╚┼ ┼╬╘╥┘
┴╬─ ($╞┼),┘ ; ╚┴╙ ╘╫╧ 255 ╔╬ ╔╘ ╘╚┼╬ ╔╘ ╔╙ ┼═╨╘┘ ┴╬─ ╙╚╧╒╠─
├═╨ #255 ; ┬┼ ┴──┼─ ╘╧ ╘╚┼ ─╔├╘╔╧╬┴╥┘.
┬┼╤ ┴──╘╧─╔├╘
╠─┴ ($╞┼),┘ ; ╔╘ ╚┴╙ ┴ ─┼╞╔╬┼─ ╨╚╥┴╙┼. ╙╘╧╥┼ ╘╚┼ ├╧─┼ ╓┴╠╒┼ ╔╬
╙╘┴ ╙╘╥╔╬╟├╧─┼+1; ╘╚┼ ╨┴╥┼╬╘ ├╧─┼
─┼┘
╠─┴ ($╞┼),┘
╙╘┴ ╙╘╥╔╬╟├╧─┼
╩═╨ ┼╧╞
┴──╘╧─╔├╘ ╠─┘ #0
- ╠─┴ ╬┼╪╘├╧─┼,┘
╙╘┴ ($╞┼),┘
╔╬┘
├╨┘ #5
┬╬┼ -
╔╬├ ╬┼╪╘├╧─┼ ; ╔╬├╥┼┴╙┼ ╘╚┼ ╬┼╪╘├╧─┼
┬╬┼ +
╔╬├ ╬┼╪╘├╧─┼+1
+ ╩╙╥ ╧╒╘╨╒╘
╠─┴ ╬┼╪╘├╧─┼+1 ; ├╚┼├╦ ╔╞ ╬┼╪╘├╧─┼=4096 ╔╞ ╙╧ ╘╚┼╬ ╞╠╒╙╚ ╘╚┼
├═╨ #>═┴╪├╧─┼ ; ─╔├╘╔╧╬┴╥┘ ┴╬─ ╙╘┴╥╘ ┴╬┼╫
┬╬┼ ├╚┼├╦┬╒═╨
╠─┴ ╬┼╪╘├╧─┼
├═╨ #<═┴╪├╧─┼
┬╬┼ ├╚┼├╦┬╒═╨
╠─┴ #<╞╠╒╙╚├╧─┼ ; ╙┼╬─ ╘╚┼ ╞╠╒╙╚ ├╧─┼ ╘╧ ╘╚┼ ├╧═╨╥┼╙╙┼─ ╞╔╠┼ ╙╧
╙╘┴ ╙╘╥╔╬╟├╧─┼ ; ╘╚┼ ─┼├╧═╨╥┼╙╙╧╥ ╫╔╠╠ ╦╬╧╫ ╘╧ ╞╠╒╙╚ ╘╚┼
╠─┴ #>╞╠╒╙╚├╧─┼ ; ─╔├╘╔╧╬┴╥┘
╙╘┴ ╙╘╥╔╬╟├╧─┼+1
╩╙╥ ╧╒╘╨╒╘
╩╙╥ ╔╬╔╘─╔├
╩═╨ ├╚┼├╦┼╧╞
├╚┼├╦┬╒═╨ ╠─┴ ╬┼╪╘┬╒═╨+1
├═╨ ╬┼╪╘├╧─┼+1 ; ├╚┼├╦┬╒═╨ ├╚┼├╦ ╘╧ ╙┼┼ ╔╞ ╘╚┼ ╬┼╪╘├╧─┼ ╚┴╙
┬╬┼ ├╚┼├╦┼╧╞ ; ╥┼┴├╚┼─ ╘╚┼ ═┴╪╔═╒═ ╓┴╠╒┼ ╞╧╥ ╘╚┼ ├╒╥╥┼╬╘
╠─┴ ╬┼╪╘┬╒═╨ ; ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ┬┼╔╬╟ ╧╒╘╨╒╘.
├═╨ ╬┼╪╘├╧─┼ ; ╞╧╥ ╪ ┬╔╘╙ ╬┼╪╘├╧─┼ ╚┴╙ ┘ ╨╚╥┴╙┼╙
┬╬┼ ├╚┼├╦┼╧╞ ; -------- -----------------------
╠─┴ #>┬╒═╨├╧─┼ ; 9 511
╙╘┴ ╙╘╥╔╬╟├╧─┼+1 ; 10 1023
╠─┴ #<┬╒═╨├╧─┼ ; 11 2047
╙╘┴ ╙╘╥╔╬╟├╧─┼ ; 12 4095
╩╙╥ ╧╒╘╨╒╘
╔╬├ ├╒╥╥┼╬╘┬╔╘╙
┴╙╠ ╬┼╪╘┬╒═╨
╥╧╠ ╬┼╪╘┬╒═╨+1
├╚┼├╦┼╧╞ ╠─┴ #0
╙╘┴ ╙╘╥╔╬╟├╧─┼+1
╠─┴ ├╚┴╥┴├╘┼╥
╙╘┴ ╙╘╥╔╬╟├╧─┼
┼╧╞ ╠─┴ 144
┬╬┼ ─╧╬┼
╩═╨ ╬┼╪╘├╚┴╥
─╧╬┼ ╩╙╥ ╧╒╘╨╒╘
╠─┴ #>┼╧╙ ; ╙┼╬─ ┴ 256 ╘╧ ╔╬─╔├┴╘┼ ┼╧╞
╙╘┴ ╙╘╥╔╬╟├╧─┼+1
╠─┴ #<┼╧╙
╙╘┴ ╙╘╥╔╬╟├╧─┼
╩╙╥ ╧╒╘╨╒╘
╠─┴ ┬╔╘═┴╙╦
┬┼╤ +
╩╙╥ $╞╞├├
╠─╪ #3
╩╙╥ $╞╞├9
╠─┴ ╥┴├╦ ; ╙┼╬─ ╫╚┴╘ ┬╔╘╙ ╫┼╥┼╬'╘ ╙┼╬─ ╫╚┼╬ ╧╒╘╨╒╘
╩╙╥ $╞╞─2
+ ╩╙╥ $╞╞├├
╠─┴ #3
╩╙╥ $╞╞├3
╠─┴ #2
╩═╨ $╞╞├3
;**********************************
; ╔╬╔╘─╔├
; ╔╬╔╘╔┴╠╔┌┼╙ ╘╚┼ ─╔├╘╔╧╬┴╥┘, ╙┼╘╙
; ╘╚┼ ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ╘╧ 9
;**********************************
╔╬╔╘─╔├ ╠─┴ #9
╙╘┴ ├╒╥╥┼╬╘┬╔╘╙
╠─┴ #>╞╔╥╙╘├╧─┼
╙╘┴ ╬┼╪╘├╧─┼+1
╠─┴ #<╞╔╥╙╘├╧─┼
╙╘┴ ╬┼╪╘├╧─┼
╠─┴ #>512
╙╘┴ ╬┼╪╘┬╒═╨+1
╠─┴ #<512
╙╘┴ ╬┼╪╘┬╒═╨
╠─┴ #<╘┴┬╠┼┬┴╙┼
╙╘┴ $╞┼
╠─┴ #>╘┴┬╠┼┬┴╙┼
╙╘┴ $╞╞
╠─┴ #<╘┴┬╠┼╙╔┌┼
╙╘┴ $╞├
╠─┴ #>╘┴┬╠┼╙╔┌┼
╙╘┴ $╞─
- ╠─┘ #0
╠─┴ #255 ; ┴╠╠ ╘╚┼ ├╧─┼ ╓┴╠╒┼╙ ┴╥┼ ╔╬╔╘ ╘╧ 255+256*255
╙╘┴ ($╞┼),┘ ; ╧╥ -1 ╔╬ ╘╫╧ ├╧═╨╠┼═┼╬╘
╔╬┘
╙╘┴ ($╞┼),┘
├╠├
╠─┴ #5 ; ┼┴├╚ ┼╬╘╥┘ ╔╬ ╘╚┼ ╘┴┬╠┼ ╘┴╦┼╙ 5 ┬┘╘┼╙
┴─├ $╞┼
╙╘┴ $╞┼
┬├├ +
╔╬├ $╞╞
+ ╠─┴ $╞├
┬╬┼ +
─┼├ $╞─
+ ─┼├ $╞├
╠─┴ $╞─
╧╥┴ $╞├
┬╬┼ -
╥╘╙
;************************************
; ╟┼╘├╚┴╥
;************************************
╟┼╘├╚┴╥ ╩╙╥ $╞╞├├
╠─╪ #2
╩╙╥ $╞╞├6
╩═╨ $╞╞├╞
;************************************
; ╧╒╘╨╒╘
;************************************
╧╒╘╨╒╘ ╠─┴ #0 ; ╘╚┼ ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ╧╒╘╨╒╘ ├┴╬ ┬┼ ╧╞ ┴ ╓┴╥╔┴┬╠┼
╙╘┴ ═┴╙╦+1 ; ╠┼╬╟╘╚,╙╧ ╘╚┼ ┬╔╘╙ ┴╥┼ ┴├├╒═╒╠┴╘┼─ ╘╧ ┴ ┬┘╘┼ ╔╙
╠─┴ #1 ; ╞╒╠╠ ┴╬─ ╘╚┼╬ ╔╘ ╔╙ ╙┼╬╘ ╘╧ ╘╚┼ ╧╒╘╨╒╘ ╞╔╠┼
╠─╪ ├╒╥╥┼╬╘┬╔╘╙
─┼╪
- ┴╙╠
╥╧╠ ═┴╙╦+1
─┼╪
┬╬┼ -
╙╘┴ ═┴╙╦
═┴╙╦─╧╬┼ ╠─┴ ═┴╙╦
╧╥┴ ═┴╙╦+1
┬╬┼ +
╥╘╙
+ ╠─┴ ═┴╙╦
┴╬─ ╙╘╥╔╬╟├╧─┼
╙╘┴ 3
╠─┴ ═┴╙╦+1
┴╬─ ╙╘╥╔╬╟├╧─┼+1
╧╥┴ 3
┬┼╤ ╬╧┬╔╘╧╬
╠─┴ ╥┴├╦
╧╥┴ ┬╔╘═┴╙╦
╙╘┴ ╥┴├╦
╬╧┬╔╘╧╬ ╠╙╥ ┬╔╘═┴╙╦
╠─┴ ┬╔╘═┴╙╦
┬╬┼ +
╩╙╥ $╞╞├├
╠─╪ #3
╩╙╥ $╞╞├9
╠─┴ ╥┴├╦
╩╙╥ $╞╞─2
╠─┴ #0
╙╘┴ ╥┴├╦
╠─┴ #128
╙╘┴ ┬╔╘═┴╙╦
+ ╠╙╥ ═┴╙╦+1
╥╧╥ ═┴╙╦
╩═╨ ═┴╙╦─╧╬┼
;******************************
; ╞╔╬─╬╧─┼
; ╘╚╔╙ ╙┼┴╥├╚┼╙ ╘╚┼ ─╔├╘╔╧╬┴╥┘ ╘╔╠╠ ╔╘ ╞╔╬─╙ ┴ ╨┴╥┼╬╘ ╬╧─┼ ╘╚┴╘ ═┴╘├╚┼╙
; ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ┴ ├╚╔╠─ ╬╧─┼ ╘╚┴╘ ═┴╘├╚┼╙ ╘╚┼ ├╚┴╥┴├╘┼╥ ╧╥ ┴ ┼═╨╘┘
; ╬╧─┼.
;*******************************
; ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ - ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ ╔╙ ╬┼┼─┼─ ┬┼├┴╒╙┼
; ╘╚┼╥┼ ┴╥┼ 4096 ╪ 4096 (16 ═╔╠╠╔╧╬) ─╔╞╞┼╥┼╬╘ ├╧═┬╔╬┴╘╔╧╬╙ ╧╞
; ├╚┴╥┴├╘┼╥ ┴╬─ ╙╘╥╔╬╟├╧─┼. ┬┘ ═╒╠╘╔╨╠┘╔╬╟ ╘╚┼ ├╚┴╥┴├╘┼╥ ┴╬─ ╙╘╥╔╬╟├╧─┼
; ╔╬ ┴ ╞╧╥═╒╠┴ ╫┼ ├┴╬ ─┼╓┼╠╧╨ ╧╞ ═┼╘╚╧─ ╧╞ ╞╔╬─╔╬╟ ╘╚┼═ ╔╬ ╘╚┼
; ─╔├╘╔╧╬┴╥┘. ╔╞ ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
; ─╧╬'╘ ═┴╘├╚ ╘╚┼ ╧╬┼╙ ╫┼ ┴╥┼ ╠╧╧╦╔╬╟ ╞╧╥ ╫┼ ├┴╠├╒╠┴╘┼ ┴╬ ╧╞╞╙┼╘
; ┴╬─ ╙┼┴╥├╚ ╘╚┼ ─╔├╘╔╧╬┴╥┘ ╞╧╥ ╘╚┼ ╥╔╟╚╘ ═┴╘├╚ ╧╥ ┴ ┼═╨╘┘
; ╙╨┴├┼ ╔╙ ╞╧╒╬─. ╔╞ ┴╬ ┼═╨╘┘ ╙╨┴├┼ ╔╙ ╞╧╒╬─ ╘╚┼╬ ╘╚┴╘ ├╚┴╥┴├╘┼╥ ┴╬─
; ╙╘╥╔╬╟├╧─┼ ├╧═┬╔╬┴╘╔╧╬ ╔╙ ╬╧╘ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
╞╔╬─╬╧─┼ ╠─┴ #0
╙╘┴ ╔╬─┼╪+1
╠─┴ ├╚┴╥┴├╘┼╥ ; ╚┼╥┼ ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ ╔╙ ┴╨╨╠╔┼─ ╘╧ ╘╚┼
┴╙╠ ; ├╚┴╥┴├╘┼╥ ┴╬─ ╘╚┼ ╙╘╥╔╬╟ ├╧─┼. ╞╧╥ ╘╚╧╙┼ ╫╚╧
╥╧╠ ╔╬─┼╪+1 ; ├┴╥┼ ╘╚┼ ╚┴╙╚╔╬╟ ╞╧╥═╒╠┴ ╔╙:
┼╧╥ ╙╘╥╔╬╟├╧─┼ ; (├╚┴╥┴├╘┼╥ << 1) ^ ╙╘╥╔╬╟├╧─┼
╙╘┴ ╔╬─┼╪ ; ╞╔╬─ ╬╧─┼ ╫╔╠╠ ╠╧╧╨ ╘╔╠╠ ╔╘ ╞╔╬─╙ ┴ ╬╧─┼
╠─┴ ╔╬─┼╪+1 ; ╘╚┴╘ ╚┴╙ ┴ ┼═╨╘┘ ╬╧─┼ ╧╥ ═┴╘├╚┼╙ ╘╚┼ ├╒╥╥┼╬╘
┼╧╥ ╙╘╥╔╬╟├╧─┼+1 ; ╨┴╥┼╬╘ ├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥
╙╘┴ ╔╬─┼╪+1
╧╥┴ ╔╬─┼╪
┬╬┼ +
╠─╪ #1
╙╘╪ ╧╞╞╙┼╘
─┼╪
╙╘╪ ╧╞╞╙┼╘+1
╩═╨ ╞╧╥┼╓┼╠╧╧╨
+ ╙┼├
╠─┴ #<╘┴┬╠┼╙╔┌┼
╙┬├ ╔╬─┼╪
╙╘┴ ╧╞╞╙┼╘
╠─┴ #>╘┴┬╠┼╙╔┌┼
╙┬├ ╔╬─┼╪+1
╙╘┴ ╧╞╞╙┼╘+1
╞╧╥┼╓┼╠╧╧╨ ╩╙╥ ├┴╠├╒╠┴╘┼
╠─┘ #0
╠─┴ ($╞┼),┘
╔╬┘
┴╬─ ($╞┼),┘
├═╨ #255
┬╬┼ +
╠─┘ #0
╥╘╙
+ ╔╬┘
- ╠─┴ ($╞┼),┘
├═╨ ╙╘╥╔╬╟├╧─┼-2,┘
┬╬┼ +
╔╬┘
├╨┘ #5
┬╬┼ -
╠─┘ #0
╥╘╙
+ ╙┼├
╠─┴ ╔╬─┼╪
╙┬├ ╧╞╞╙┼╘
╙╘┴ ╔╬─┼╪
╠─┴ ╔╬─┼╪+1
╙┬├ ╧╞╞╙┼╘+1
╙╘┴ ╔╬─┼╪+1
┴╬─ #128
┬┼╤ ╞╧╥┼╓┼╠╧╧╨
├╠├
╠─┴ #<╘┴┬╠┼╙╔┌┼
┴─├ ╔╬─┼╪
╙╘┴ ╔╬─┼╪
╠─┴ #>╘┴┬╠┼╙╔┌┼
┴─├ ╔╬─┼╪+1
╙╘┴ ╔╬─┼╪+1
╩═╨ ╞╧╥┼╓┼╠╧╧╨
;***************************
; ├┴╠├╒╠┴╘┼
; ╘┴╦┼╙ ╘╚┼ ╓┴╠╒┼ ╔╬ ╔╬─┼╪ ┴╬─ ├┴╠├╒╠┴╘┼╙ ╔╘╙ ╠╧├┴╘╔╧╬ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
;****************************
├┴╠├╒╠┴╘┼ ╠─┴ ╔╬─┼╪
╙╘┴ $╞┼
╠─┴ ╔╬─┼╪+1
╙╘┴ $╞╞
┴╙╠ $╞┼
╥╧╠ $╞╞
┴╙╠ $╞┼
╥╧╠ $╞╞
├╠├
╠─┴ ╔╬─┼╪
┴─├ $╞┼
╙╘┴ $╞┼
╠─┴ ╔╬─┼╪+1
┴─├ $╞╞
╙╘┴ $╞╞
├╠├
╠─┴ #<╘┴┬╠┼┬┴╙┼
┴─├ $╞┼
╙╘┴ $╞┼
╠─┴ #>╘┴┬╠┼┬┴╙┼
┴─├ $╞╞
╙╘┴ $╞╞
╠─┘ #0
╥╘╙
;******************************
; ─┼├╧─┼╙╘╥╔╬╟
;******************************
─┼├╧─┼╙╘╥╔╬╟ ╘┘┴ ; ─┼├╧─┼╙╘╥╔╬╟ ╨╒╘╙ ╘╚┼ ╙╘╥╔╬╟ ╧╬ ╘╚┼ ╙╘┴├╦
╙╘┴ ├╧╒╬╘ ; ╔╬ ┴ ╠╔╞╧ ╞┴╙╚╔╧╬.
╠─╪ #>─┼├╧─┼╙╘┴├╦
├╠├
┴─├ #<─┼├╧─┼╙╘┴├╦
╙╘┴ $╞├
╙╘╪ $╞─
╠─┴ #0
╙╘┴ ├╧╒╬╘+1
- ╠─┴ ╔╬─┼╪+1
┬┼╤ +
╩╙╥ ├┴╠├╒╠┴╘┼
╠─┘ #4
╠─┴ ($╞┼),┘
╠─┘ #0
╙╘┴ ($╞├),┘
╠─┘ #2
╠─┴ ($╞┼),┘
╙╘┴ ╔╬─┼╪
╔╬┘
╠─┴ ($╞┼),┘
╙╘┴ ╔╬─┼╪+1
╩╙╥ ╔╬╞├
╩═╨ -
+ ╠─┘ #0
╠─┴ ╔╬─┼╪
╙╘┴ ($╞├),┘
╔╬├ ├╧╒╬╘
┬╬┼ +
╔╬├ ├╧╒╬╘+1
+ ╥╘╙
;******************************
; ╔╬╨╒╘
;******************************
╔╬╨╒╘ ╠─┴ #0 ; ╘╚┼ ╔╬╨╒╘ ╥╧╒╘╔╬┼╙ ╔╙ ╒╙┼─ ┬┘ ╘╚┼ ─┼├╧═╨╥┼╙╙╧╥
╙╘┴ ═┴╙╦+1 ; ╘╧ ╥┼┴─ ╔╬ ╘╚┼ ╓┴╥╔┴┬╠┼ ╠┼╬╟╘╚ ├╧─┼╙
╙╘┴ ╥┼╘╒╥╬
╙╘┴ ╥┼╘╒╥╬+1
╠─┴ #1
╠─╪ ├╒╥╥┼╬╘┬╔╘╙
─┼╪
- ┴╙╠
╥╧╠ ═┴╙╦+1
─┼╪
┬╬┼ -
╙╘┴ ═┴╙╦
- ╠─┴ ═┴╙╦
╧╥┴ ═┴╙╦+1
┬┼╤ ╔╬╨╒╘─╧╬┼
╠─┴ ┬╔╘═┴╙╦
┬╨╠ +
╩╙╥ ╟┼╘├╚┴╥
╙╘┴ ╥┴├╦
+ ╠─┴ ╥┴├╦
┴╬─ ┬╔╘═┴╙╦
┬┼╤ +
╠─┴ ═┴╙╦
╧╥┴ ╥┼╘╒╥╬
╙╘┴ ╥┼╘╒╥╬
╠─┴ ═┴╙╦+1
╧╥┴ ╥┼╘╒╥╬+1
╙╘┴ ╥┼╘╒╥╬+1
+ ╠╙╥ ═┴╙╦+1
╥╧╥ ═┴╙╦
╠╙╥ ┬╔╘═┴╙╦
╠─┴ ┬╔╘═┴╙╦
┬╬┼ +
╠─┴ #128
╙╘┴ ┬╔╘═┴╙╦
+ ╩═╨ -
╔╬╨╒╘─╧╬┼ ╥╘╙
;*******************************
; ┼╪╨┴╬─╞╔╠┼
; ╫╚┼╥┼ ╘╚┼ ─┼├╧═╨╥┼╙╙╔╧╬ ╔╙ ─╧╬┼
;*******************************
┼╪╨┴╬─╞╔╠┼ ╠─┴ #0
╙╘┴ ╥┴├╦
╠─┴ #128
╙╘┴ ┬╔╘═┴╙╦
╙╘┴╥╘ ╩╙╥ ╔╬╔╘─╔├
╩╙╥ ╔╬╨╒╘
╠─┴ ╥┼╘╒╥╬+1
╙╘┴ ╧╠─├╧─┼+1 ; ╙AVE THE FIRST CHARACTER IN ╧╠─├╧─┼
╠─┴ ╥┼╘╒╥╬
╙╘┴ ├╚┴╥┴├╘┼╥
╙╘┴ ╧╠─├╧─┼
├═╨ #<┼╧╙
┬╬┼ +
╠─┴ ╥┼╘╒╥╬+1 ; ╔F RETURN = ┼╧╙ (256) THEN ALL DONE
├═╨ #>┼╧╙
┬╬┼ +
╩═╨ ├╠╧╙┼
+ ╩╙╥ $╞╞├├
╠─╪ #3
╩╙╥ $╞╞├9
╠─┴ ╧╠─├╧─┼ ; ╙END OLDCODE TO THE OUTPUT FILE
╩╙╥ $╞╞─2
╬┼╪╘ ╩╙╥ ╔╬╨╒╘
╠─┴ ╥┼╘╒╥╬
╙╘┴ ╬┼╫├╧─┼
╠─┴ ╥┼╘╒╥╬+1
╙╘┴ ╬┼╫├╧─┼+1
├═╨ #1 ; ┴LL OF THE SPECIAL CODES ╞LUSHCODE,┬UMP├ODE & ┼╧╙
┬╬┼ ++ ; ╚AVE 1 FOR A ═╙┬.
╠─┴ ╬┼╫├╧─┼
├═╨ #<┬╒═╨├╧─┼
┬╬┼ +
╔╬├ ├╒╥╥┼╬╘┬╔╘╙
╩═╨ ╬┼╪╘
+ ├═╨ #<╞╠╒╙╚├╧─┼
┬┼╤ ╙╘┴╥╘
├═╨ #<┼╧╙
┬╬┼ +
╩═╨ ├╠╧╙┼
+ ╙┼├ ; ╚ERE WE COMPARE THE NEWCODE JUST READ IN TO THE
╠─┴ ╬┼╫├╧─┼ ; NEXT CODE. ╔F NEWCODE IS GREATER THAN IT IS A
╙┬├ ╬┼╪╘├╧─┼ ; ┴├╒╘┼┴├╒╘┼┴ SITUATION AND MUST BE HANDLE DIFFERENTLY.
╙╘┴ 3
╠─┴ ╬┼╫├╧─┼+1
╙┬├ ╬┼╪╘├╧─┼+1
╧╥┴ 3
┬├├ +
╠─┴ ├╚┴╥┴├╘┼╥
╙╘┴ ─┼├╧─┼╙╘┴├╦
╠─┴ ╧╠─├╧─┼
╙╘┴ ╔╬─┼╪
╠─┴ ╧╠─├╧─┼+1
╙╘┴ ╔╬─┼╪+1
╠─┘ #1
┬╬┼ ++
+ ╠─┴ ╬┼╫├╧─┼ ; ╨OINT INDEX TO NEWCODE SPOT IN THE DICTIONARY
╙╘┴ ╔╬─┼╪ ; ╙O ─┼├╧─┼╙╘╥╔╬╟ HAS A PLACE TO START
╠─┴ ╬┼╫├╧─┼+1
╙╘┴ ╔╬─┼╪+1
╠─┘ #0
+ ╩╙╥ ─┼├╧─┼╙╘╥╔╬╟
╠─┘ #0
╠─┴ ($╞├),┘
╙╘┴ ├╚┴╥┴├╘┼╥
╔╬├ $╞├
┬╬┼ +
╔╬├ $╞─
+ ╩╙╥ $╞╞├├
╠─╪ #3
╩╙╥ $╞╞├9
╠1 ╠─┴ ├╧╒╬╘+1 ; ├OUNT CONTAINS THE NUMBER OF CHARACTERS ON THE STACK
╧╥┴ ├╧╒╬╘
┬┼╤ +
╩╙╥ ─┼├╞├
╠─┘ #0
╠─┴ ($╞├),┘
╩╙╥ $╞╞─2
╩═╨ ╠1
+ ╠─┴ ╬┼╪╘├╧─┼ ; ├ALCULATE THE SPOT IN THE DICTIONARY FOR THE STRING
╙╘┴ ╔╬─┼╪ ; THAT WAS JUST ENTERED.
╠─┴ ╬┼╪╘├╧─┼+1
╙╘┴ ╔╬─┼╪+1
╩╙╥ ├┴╠├╒╠┴╘┼
╠─┘ #2 ; ╘HE LAST CHARACTER READ IN IS TACKED ONTO THE END
╠─┴ ╧╠─├╧─┼ ; OF THE STRING THAT WAS JUST TAKEN OFF THE STACK
╙╘┴ ($╞┼),┘ ; ╘HE NEXTCODE IS THEN INCREMENTED TO PREPARE FOR THE
╔╬┘ ; NEXT ENTRY.
╠─┴ ╧╠─├╧─┼+1
╙╘┴ ($╞┼),┘
╔╬┘
╠─┴ ├╚┴╥┴├╘┼╥
╙╘┴ ($╞┼),┘
╔╬├ ╬┼╪╘├╧─┼
┬╬┼ +
╔╬├ ╬┼╪╘├╧─┼+1
+ ╠─┴ ╬┼╫├╧─┼
╙╘┴ ╧╠─├╧─┼
╠─┴ ╬┼╫├╧─┼+1
╙╘┴ ╧╠─├╧─┼+1
╩═╨ ╬┼╪╘
├╠╧╙┼ ╩╙╥ $╞╞├├
╠─┴ #2
╩╙╥ $╞╞├3
╠─┴ #3
╩═╨ $╞╞├3
─┼├╞├ ╠─┴ $╞├
┬╬┼ +
─┼├ $╞─
+ ─┼├ $╞├
╠─┴ ├╧╒╬╘
┬╬┼ +
─┼├ ├╧╒╬╘+1
+ ─┼├ ├╧╒╬╘
╥╘╙
╔╬╞├ ╔╬├ $╞├
┬╬┼ +
╔╬├ $╞─
+ ╔╬├ ├╧╒╬╘
┬╬┼ +
╔╬├ ├╧╒╬╘+1
+ ╥╘╙
╬┼╪╘├╧─┼ .╫╧╥ 0
╙╘╥╔╬╟├╧─┼ .╫╧╥ 0
├╚┴╥┴├╘┼╥ .┬┘╘ 0
╬┼╪╘┬╒═╨ .╫╧╥ 0
├╒╥╥┼╬╘┬╔╘╙ .┬┘╘ 0
╥┴├╦ .┬┘╘ 0
┬╔╘═┴╙╦ .┬┘╘ 0
═┴╙╦ .╫╧╥ 0
╔╬─┼╪ .╫╧╥ 0
╧╞╞╙┼╘ .╫╧╥ 0
╥┼╘╒╥╬ .╫╧╥ 0
├╧╒╬╘ .╫╧╥ 0
╬┼╫├╧─┼ .╫╧╥ 0
╧╠─├╧─┼ .╫╧╥ 0
╘┼╙╘ .┬┘╘ 0
╘╧ ─╥╔╓┼ ╘╚┼ ═╠ ╔ ╫╥╧╘┼ ╘╚╔╙ ╙═┴╠╠ ┬┴╙╔├ ╨╥╧╟╥┴═. ╬╧╘┼ ╘╚┴╘ ├╚┴╬╬┼╠ ╘╫╧ ╔╙
┴╠╫┴┘╙ ╘╚┼ ╔╬╨╒╘ ┴╬─ ├╚┴╬╬┼╠ ╘╚╥┼┼ ╔╙ ┴╠╫┴┘╙ ╘╚┼ ╧╒╘╨╒╘. ┼╪ ┴╬─ ├╧ ═┴┘ ┬┼
├╚┴╬╟┼─ ╘╧ ╙╒╔╘ ╫╚┴╘┼╓┼╥ ╠╧├┴╘╔╧╬╙ ╘╚┼ ╨╥╧╟╥┴═ ╔╙ ╥┼┴╙╙┼═┬╠┼─ ┴╘.
1 ╔╞┴=.╘╚┼╬┴=1:╠╧┴─"╠┌╫.═╠",╨┼┼╦(186),1
10 ┼╪=2500:├╧=2503
15 ╨╥╔╬╘"[┼]╪╨┴╬─ ╧╥ [├]╧═╨╥┼╙╙?"
20 ╟┼╘┴$:╔╞┴$<>"├"┴╬─┴$<>"┼"╘╚┼╬20
30 ╔╬╨╒╘"╬┴═┼ ╧╞ ╔╬╨╒╘ ╞╔╠┼";╞╔$:╔╞╠┼╬(╞╔$)=.╘╚┼╬30
40 ╔╬╨╒╘"╬┴═┼ ╧╞ ╧╒╘╨╒╘ ╞╔╠┼";╞╧$:╔╞╠┼╬(╞╧$)=.╘╚┼╬40
50 ╧╨┼╬2,9,2,╞╔$+",╨,╥":╧╨┼╬3,9,3,╞╧$+",╨,╫"
60 ╔╞┴$="┼"╘╚┼╬╙┘╙┼╪
70 ╔╞┴$="├"╘╚┼╬╙┘╙├╧
80 ┼╬─
╞OR THOSE INTERESTED IN LEARNING MORE ABOUT DATA
COMPRESSION/DECOMPRESSION ╔ RECOMMEND THE BOOK '╘HE ─ATA ├OMPRESSION
┬OOK' WRITTEN BY ═ARK ╬ELSON. ╔ LEARNED A GREAT DEAL FROM READING THIS
BOOK. ╔T EXPLAINS ALL OF THE MAJOR DATA COMPRESSION METHODS. (HUFFMAN
CODING, DICTIONARY TYPE COMPRESSION SUCH AS ╠┌╫, ARITHMATIC CODING,
SPEECH COMPRESSION AND LOSSY GRAPHICS COMPRESSION)
╤UESTIONS OR COMMENTS ARE WELCOME, THEY MAY BE DIRECTED TO ME AT :
╔NTERNET : ┬LUCIER@ERSYS.EDMONTON.AB.CA
╟ENIE : B.LUCIER1
------------------------------------------------------------------------------
BEGIN 644 LZW.ML
═╤└┼,╬└╨@╟╨╩╔@(╫╘#:─└├?,-(.╠*├>╘-╩0"-[@╘@┌╨╩-[╨╘@6└╬╤_╠@╤_╠╟_
═\└┌╤_╚╫╬#8┬╤_╚╫═#4╤╚"╩└└╬>╠-─?[(╨└70]╬[╦#=└#[╬╨-(/8*╦>╨-╥1#0
═&╩╫╦#<─└╘!.╔└╚╫═#:─!├>╪-(/8*()\*3%╘*╦?$-╙>╨-╘!┌═\└╫-┌╨╫0%╩─!
═├>╪-╩0&-[0╘@]@╦╬\@╘.\└╘╬\0╓╔└(╫╬#:╫╧#8╫═#:60╘└-,╫╨─@]@╩╔└8╫╬
═#:─└├>╘-(/8*╦?0-\└╪@╙/^┬└╥#)_┌╫╙#2#2_╥#,_┌─#(,/_╩0),╨_^╔"8╫╥
═#:─!├>╨-╩0.-┌╨╓╔└╚╫╤#:─└├?└-╩0"%_╩─╪┴?^╔╟87\╩1.%_:└└╩?^1_╠┬1
═_┴┬╔!67^┴?┌0└╬;_╔?╙0└╠;]╤╧╥┼_07\╘-┘@(,╙_╚@(@╤╧],╙_^╔└(╫╓#:─!
═╦╧(-╥@╚╬]@╫*╘/╞-]0╓═]0╘-]@╫0└6"═]0╘═[0╓%└┌╫╓#2╫╬#04#\└╞═\╨╘-
═]└╓-\╨╒.]└╓═]└╫0&"#,_┌(#(,╟_╦?,-(-+_╩0"-\╨╓╔@(╫╘#4[╓#6[╒#4╨+
═"┌─└├?@-╦>\-"┬[╪#4╫═#8╫╫#:╫╪#4╫╬#8╫╪#=└1╦?<-╘└╥┬└8[┘#<╩.^@╒,
═┼╨╠╪╩9╫═]╨╓-^0╓╔$^╫╪#8╫┌#2#├"┌└└╠?[(,?[)_]└#╚└!@╥+'^╓>╠-╘└├(
═╨└70]*└└8#┬═]╨╫═^0╓-]╨╓═^└╫═^@╓-^└╘╔@/└1&*╞=;?<-├?<-╩1-═^└╓-
═^└╒,┼╨╬═]╨╓%_╩╫╪#87_!╧╪╞_╨;^)╧\8╦?<-9?┌%_╩╫╪#67_┴?\8╩0!┼_╚7^
═╩3┴┼_╪7_╚└!@╞(╫]#:(─&&┼4┴?╥&_:─└├?╪-╦?@-\!╪@╪╨╬@!+'^╚└"1_*└"
═╠?┌-]╨╫(╠?┌-^└╘@╫└╒,)@╥@└*╫╫#9'\[╧╘-╘└/╬_@╒@╩0"-]@╓-^╨╓-_└╓╔
═└:[╥#<╚*+╧8-╥═#┘├?4-╦?4-#?8-\#╬═]└╘0!┬#╦"╚╫╙#:╫╙#2╫╘#?└2╦?4-
═#?╠-├?╠-╦?8-#?╨-├?╨-3╧8-;╧4-3╧0-╦?0-╘└6╔@(╫╘#4╤╘#&"╔└(╫╙#:╞└
═├?0-()\*(%─,╦?╨-├0(.╦?╠-├>\-├0$.╥0#0"╩╫\#<─!╘└-,╬╨╘@╙/^┬└╥#)
═_┌╘!#┬#2_╥!9#*╫[#8╫_#:╫\#8╘└#╠─!╘!┬═_╨╫)└=└&[╧(-3/,,╥0+╨╩\─└
═╘└-,╬╨╘╪╦?\-[>╠-┴0.═└└[═[└╘%└┘└6╦>\-├50─╦0$.├?<-╦0(.├?@-╚└'0
═#╩╫_#8╫╫#:╘└#╚╫╪#:└└(!0,╚└"╤_(╫╧#>;\╘└+╞_2#,_┌(#(,╟_╦?╪-#?╘-
═\└╘@╥└╓@└+'\(-+_3&╘-╦>╠-├?<-╦>╨-├?@-(.,+╚└*═└0┌1_╠┬═└@┌1_╠┬═
═[╨╓1_╬[╦#=└#[╬╨-╦?\-├0$.╦0└.├0(.3/,,(,╙_╩0(@╨_^╔└╘╙#_┌7\╘└+&
═_<;\╦?╘-╘└/._@╫._0╒@┘╧╙0└╬;][╧╘-╘└/╬_@╒@└└└└└└└└└└└└└└└└└└└└
*└└└└└└└└└└└└└└└└
└
END
CRC32 FOR LZW.ML = 2460116527
BEGIN 644 LZW.BAS
═└0@<"└$└┬╘&╥+╩=!╠├$┌─╥),6┼<╬34╨┬+#─╠,0└╨"└╚└15┬╥,├4╨,#╔#3[(╥
═-3└╙└%└(#╨"9(╔,219)84$%.1"!/4┬└20┘)/35!215-3/╥(└;└@4└*%!)#╩+
═022╙╠2)#(╩]!)+.╤(─4┬╔╙(╨└)<('@"%(─┘!344@3╘8@24┘0550@1─┼,12([
═1───.╚╧#*$9))"╞╥+╩<╙,└##""@└┴2).04╒%($]&($]55%!55"!&24╤%(├═&
═3╥0┌┬\,╚1─\─*;(╬╔╙0╨└.╠(,@"?,┬╨┘+#(╠1───╩┬(╠4╥╤2(├╩?,╥╨┘+#,╠
═1─\─╩┬(╠4"╤7(@#["#╨└┬╘$─╠┬)%(╩>>15@└"╨┼&└(═!)+(┬0╥*╟╟─-/└└└└
└
END
CRC32 FOR LZW.BAS = 100674089
===============================================================================
╘╚╥┼┼-╦┼┘ ╥╧╠╠╧╓┼╥ FOR THE ├-128 AND ├-64.
BY ├RAIG ┬RUCE <CSBRUCE@NEUMANN.UWATERLOO.CA>
1. ╔╬╘╥╧─╒├╘╔╧╬
╘HIS ARTICLE EXAMINES A THREE-KEY ROLLOVER MECHANISM FOR THE KEYBOARDS OF THE
├-128 AND ├-64 AND PRESENTS ╦ERNAL-WEDGE IMPLEMENTATIONS FOR BOTH MACHINES.
╫EBSTER'S DOESN'T SEEM TO KNOW, SO ╔'LL TELL YOU THAT THIS MEANS THAT THE
MACHINE WILL ACT SENSIBLY IF YOU ARE HOLDING DOWN ONE KEY AND THEN PRESS
ANOTHER WITHOUT RELEASING THE FIRST (OR EVEN PRESS A THIRD KEY WHILE HOLDING
DOWN TWO OTHERS). ╘HIS IS USEFUL TO FAST TOUCH TYPERS. ╔N FACT, FAST TYPING
WITHOUT ROLLOVER CAN BE QUITE ANNOYING; YOU GET A LOT OF MISSING LETTERS.
┴NOTHER ANNOYING PROPERTY OF THE KERNEL KEYSCANNING IS JOYSTICK INTERFERENCE.
╔F YOU MOVE THE JOYSTICK PLUGGED INTO PORT #1, YOU WILL NOTICE THAT SOME JUNK
KEYSTROKES RESULT. ╘HE KEYSCANNERS HERE ELIMINATE THIS PROBLEM BY SIMPLY
CHECKING IF THE JOYSTICK IS PRESSED AND IGNORING THE KEYBOARD IF IT IS.
╘HE REASON THAT A 3-KEY ROLLOVER IS IMPLEMENTED INSTEAD OF THE MORE GENERAL
╬-KEY ROLLOVER IS THAT SCANNING THE KEYBOARD BECOMES MORE AND MORE UNRELIABLE
AS MORE KEYS ARE HELD DOWN. ╦EY "SHADDOWS" BEGIN TO APPEAR TO MAKE IT LOOK
LIKE YOU ARE HOLDING DOWN A CERTAIN KEY WHEN YOU REALLY ARE NOT. ╙O, BY
LIMITING THE NUMBER OF KEYS SCANNED TO 3, SOME OF THIS CAN BE AVOIDED. ┘OU
WILL GET STRANGE RESULTS IF YOU HOLD DOWN MORE THAN THREE KEYS AT A TIME, AND
EVEN SOMETIMES WHEN HOLDING DOWN 3 OR LESS. ╘HE "SHIFT" KEYS (╙HIFT,
├OMMODORE, ├ONTROL, ┴LTERNATE, AND ├APS╠OCK) DON'T COUNT IN THE 3 KEYS OF
ROLLOVER, BUT THEY DO MAKE THE KEYBOARD HARDER TO READ CORRECTLY.
╞ORTUNATELY, THREE KEYS WILL ALLOW YOU TO TYPE WORDS LIKE "┴╬─" AND "╘╚┼"
WITHOUT RELEASING ANY KEYS.
2. ╒╙┼╥ ╟╒╔─┼
╒SING THESE UTILITIES IS REALLY EASY - YOU JUST TYPE AWAY LIKE NORMAL. ╘O
INSTALL THE ├-128 VERSION, ENTER:
┬╧╧╘ "╦┼┘╙├┴╬128"
AND YOU'RE IN BUSINESS. ╘HE PROGRAM WILL DISPLAY "╦EYSCAN128 INSTALLED" AND
GO TO WORK. ╘HE PROGRAM LOADS INTO MEMORY AT ADDRESSES $1500-$17┬┴ (5376-6074
DECIMAL), SO YOU'LL WANT TO WATCH OUT FOR CONFLICTS WITH OTHER UTILITIES.
╘HIS PROGRAM ALSO TAKES OVER THE ╔╥╤ VECTOR AND THE ┬┴╙╔├ RESTART VECTOR
($┴00). ╘HE PROGRAM WILL SURVIVE A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼. ╘O UNINSTALL THIS
PROGRAM, YOU MUST RESET THE MACHINE (OR POKE THE KERNEL VALUES BACK INTO THE
VECTORS); IT DOES NOT UNINSTALL ITSELF.
╠OADING THE ├-64 VERSION IS A BIT TRICKIER, SO A SMALL ┬┴╙╔├ LOADER PROGRAM IS
PROVIDED. ╠╧┴─ AND ╥╒╬ THE "╦┼┘╙├┴╬64.┬╧╧╘" PROGRAM. ╔T WILL LOAD THE
"╦┼┘╙├┴╬64" PROGRAM INTO MEMORY AT ADDRESSES $├500-$├77┼ (50432-51070 DECIMAL)
AND EXECUTE IT (WITH A ╙┘╙ 50432). ╘O UNINSTALL THE PROGRAM, ENTER ╙┘╙ 50435.
╘HE PROGRAM TAKES OVER THE ╔╥╤ AND ╬═╔ VECTORS AND ONLY GIVES THEM BACK TO THE
KERNEL UPON UNINSTALLATION. ╘HE PROGRAM WILL SURVIVE A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼.
╙OMETHING THAT YOU MAY OR MAY NOT KNOW ABOUT THE ├-64 IS THAT ITS KEYS CAN BE
MADE TO REPEAT BY POKING TO ADDRESS 650 DECIMAL. ╨╧╦┼650,128 WILL ENABLE THE
REPEATING OF ALL KEYS. ╨╧╦┼650,0 WILL ENABLE ONLY THE REPEATING OF THE ╙╨┴├┼,
─┼╠┼╘┼, AND ├╒╥╙╧╥ KEYS. ╨╧╦┼650,64 WILL DISABLE THE REPEATING OF ALL KEYS.
┴N UNUSUAL SIDE EFFECT OF CHANGING THIS TO EITHER FULL REPEAT OR NO REPEAT IS
THAT HOLDING DOWN ╙╚╔╞╘+├╧══╧─╧╥┼ (CHARACTER SET SHIFT) WILL REPEAT RAPIDLY.
╘O SEE THE ROLLOVER IN ACTION, HOLD DOWN THE "╩" KEY FOR A WHILE, AND THEN
PRESS "╦" WITHOUT RELEASING "╩". "╦" WILL COME OUT AS EXPECTED, AS IT WOULD
WITH THE KERNAL. ╬OW, RELEASE THE "╩" KEY. ╔F YOU ARE ON A ├-128, YOU WILL
NOTICE THAT THE "╦" KEY WILL NOW STOP REPEATING (THIS IS ACTUALLY AN IMPORTANT
FEATURE - IT AVOIDS PROBLEMS IF YOU DON'T RELEASE ALL OF THE KEYS YOU ARE
HOLDING DOWN, AT ONCE). ╬OW, PRESS AND HOLD THE "╩" KEY AGAIN WITHOUT
RELEASING THE "╦". "╩" WILL NOW APPEAR. ╔T WOULDN'T USING THE ╦ERNAL KEY
SCANNER. ┘OU CAN ALSO TRY THIS WITH 3-KEY COMBINATIONS. ╘HERE WILL BE SOME
COMBINATIONS THAT CAUSE PROBLEMS; MORE ON THIS BELOW.
┴LSO, TAKE A SPAZ ON THE JOYSTICK PLUGGED INTO PORT #1 AND OBSERVE THAT NO
GARBAGE GETS TYPED IN. ╘HIS WAS AN ANNOYING PROBLEM WITH THE KERNEL OF BOTH
THE 64 AND 128 AND HAS LEAD MANY DIFFERENT GAMES TO PICKING BETWEEN JOYSTICK
#1 AND #2 AS THE PRIMARY CONTROLLER. ╘HE JOYSTICK IN PORT #2 IS NOT A PROBLEM
TO EITHER ╦EYSCAN-128/64 OR THE ╦ERNAL.
3. ╦┼┘┬╧┴╥─ ╙├┴╬╬╔╬╟
╘HE ╦ERNAL SCANS THE KEYBOARD SIXTY TIMES A SECOND TO SEE WHAT KEYS YOU ARE
HOLDING DOWN. ┬ECAUSE OF HARDWARE PECULIARITIES, THERE ARE MULTIPLE SCANNING
TECHNIQUES THAT WILL GIVE DIFFERENT RESULTS.
3.1. ╙├┴╬╬╔╬╟ ┼╪┴═╨╠┼
┴N EXAMPLE PROGRAM IS INCLUDED TO DEMONSTRATE DIFFERENT KEYBOARD SCANNING
TECHNIQUES POSSIBLE. ╘O RUN IT FROM A ├-128 IN 40-COLUMN (SLOW) MODE, ENTER:
┬╧╧╘ "╦┼┘╙╚╧╫"
╧N A ├-64, YOU MUST:
╠╧┴─ "╦┼┘╙╚╧╫",8,1
AND THEN:
╙┘╙ 4864
╘HE SAME PROGRAM WORKS ON BOTH MACHINES. ╞OUR MAPS OF THE KEYSCANNING MATRIX
WILL BE DISPLAYED ON THE 40-COLUMN SCREEN, AS SCANNED BY DIFFERENT TECHNIQUES.
╘HE LEFTMOST ONE IS SCANNED FROM TOP TO BOTTOM "QUICKLY". ╘HE SECOND FROM THE
LEFT SCANS FROM BOTTOM TO TOP "QUICKLY". ╘HE THIRD FROM THE LEFT SCANS THE
KEYBOARD SIDEWAYS, AND THE RIGHTMOST MATRIX SCANS THE KEYS FROM TOP TO BOTTOM
"SLOWLY".
╘HE MAPPING OF KEYSCAN MATRIX POSITIONS TO KEYS IS AS FOLLOWS:
╥╧╫╙: \ ├╧╠╒═╬╙: PEEK($─├01)
POKE \
$─├00 \ 128 64 32 16 8 4 2 1
+-------+-------+-------+-------+-------+-------+-------+-------+
255-1 ▄ ─╧╫╬ ▄ ╞5 ▄ ╞3 ▄ ╞1 ▄ ╞7 ▄ ╥╔╟╚╘ ▄ ╥┼╘╒╥╬▄ ─┼╠┼╘┼▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-2 ▄╠┼╞╘-╙╚▄ ┼ ▄ ╙ ▄ ┌ ▄ 4 ▄ ┴ ▄ ╫ ▄ 3 ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-4 ▄ ╪ ▄ ╘ ▄ ╞ ▄ ├ ▄ 6 ▄ ─ ▄ ╥ ▄ 5 ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-8 ▄ ╓ ▄ ╒ ▄ ╚ ▄ ┬ ▄ 8 ▄ ╟ ▄ ┘ ▄ 7 ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-16 ▄ ╬ ▄ ╧ ▄ ╦ ▄ ═ ▄ 0 ▄ ╩ ▄ ╔ ▄ 9 ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-32 ▄ , ▄ @ ▄ : ▄ . ▄ - ▄ ╠ ▄ ╨ ▄ + ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-64 ▄ / ▄ ^ ▄ = ▄╥╟╚╘-╙╚▄ ╚╧═┼ ▄ ; ▄ * ▄ \ ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-128 ▄ ╙╘╧╨ ▄ ╤ ▄├╧══╧─╥▄ ╙╨┴├┼ ▄ 2 ▄├╧╬╘╥╧╠▄ _ ▄ 1 ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
╘HE FOLLOWING TABLE CONTAINS THE ADDITIONAL KEYS WHICH MUST BE SCANNED ON THE
├128 (BUT WHICH ARE NOT DISPLAYED BY THE EXAMPLE SCANNING PROGRAM).
╥╧╫╙: \ ├╧╠╒═╬╙: PEEK($─├01)
POKE \
$─02╞ \ 128 64 32 16 8 4 2 1
+-------+-------+-------+-------+-------+-------+-------+-------+
255-1 ▄ 1 ▄ 7 ▄ 4 ▄ 2 ▄ ╘┴┬ ▄ 5 ▄ 8 ▄ ╚┼╠╨ ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-2 ▄ 3 ▄ 9 ▄ 6 ▄ ┼╬╘┼╥ ▄ ╠╞ ▄ - ▄ + ▄ ┼╙├ ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
255-4 ▄╬╧-╙├╥╠▄ ╥╔╟╚╘ ▄ ╠┼╞╘ ▄ ─╧╫╬ ▄ ╒╨ ▄ . ▄ 0 ▄ ┴╠╘ ▄
+-------+-------+-------+-------+-------+-------+-------+-------+
╘HESE TABLES ARE PRESENTED ON PAGE 642 OF THE ├OMMODORE 128 ╨ROGRAMMER'S
╥EFERENCE ╟UIDE. ╘HE SCAN CODES THAT ARE STORED IN LOCATION 212 ON THE ├128
AND LOCATION 197 ON THE ├64 ARE CALCULATED BASED ON THE ABOVE TABLES. ╘HE
ENTRY IN THE "1" BIT POSITION OF THE FIRST LINE OF THE FIRST TABLE (─┼╠┼╘┼)
HAS A SCAN CODE OF 0, THE "2" ENTRY (╥┼╘╒╥╬) HAS A SCAN CODE OF 1, ETC., THE
ENTRY ON THE SECOND SCAN LINE IN THE "1" POSITION ("3") HAS A SCAN CODE OF 8,
ETC., ALL THE WAY DOWN TO CODE 63. ╘HE SCAN CODES FOR THE 128 GO ALL THE WAY
TO 87, CONTINUING IN THE SECOND TABLE LIKE THE FIRST.
┘OU WILL NOTICE SOME STRANGE EFFECTS OF THE DIFFERENT SCANNING TECHNIQUES WHEN
YOU HOLD DOWN MULTIPLE KEYS. ═ORE ON THIS BELOW. ┴LSO TRY PUSHING JOYSTICK
#1 AROUND.
3.2. ╙├┴╬╬╔╬╟ ╚┴╥─╫┴╥┼
╘O SCAN THE 128 KEYBOARD, YOU MUST POKE A VALUE INTO $─├00 (├╔┴#1 PORT ┴) AND
$─02╞ (╓╔├ CHIP KEYBOARD SELECT PORT) TO SELECT THE ROW TO BE SCANNED. ╘HE
─ATA ─IRECTION ╥EGISTER FOR THIS PORT WILL BE SET TO ALL OUTPUTS BY THE
╦ERNAL, SO YOU DON'T HAVE TO WORRY ABOUT IT. ┼ACH BIT OF $─├00 AND THE THREE
LEAST SIGNIFICANT BITS OF $─02╞ ARE USED FOR SELECTING ROWS. ┴ "0" BIT MEANS
THAT A ROW ╔╙ SELECTED, AND A "1" MEANS THAT A ROW ╔╙ ╬╧╘ SELECTED. ╘HE POKE
VALUE TO USE FOR SELECTING AMONG THE VARIOUS ROWS ARE GIVEN IN THE TWO TABLES
IN THE PREVIOUS SECTION.
╒SING ONE BIT PER ROW ALLOWS YOU TO SELECT MULTIPLE ROWS AT THE SAME TIME. ╔T
CAN BE USEFUL TO SELECT ALL ROWS AT ONE TIME OR NO ROWS. ╘O READ THE ROW THAT
HAS BEEN SELECTED, SIMPLY PEEK AT LOCATION $─├01 (├╔┴#1 PORT ┬). ┼ACH BIT
WILL TELL YOU WHETHER THE CORRESPONDING KEY IS CURRENTLY BEING HELD DOWN OR
NOT. ┴GAIN, WE HAVE REVERSE LOGIC; A "0" MEANS THAT THE KEY IS BEING HELD
DOWN, AND A "1" MEANS THAT THE KEY IS NOT HELD DOWN. ╘HE BIT VALUES
CORRESPONDING TO THE KEYS ARE GIVEN AS THE COLUMN HEADINGS IN THE TABLES IN
THE PREVIOUS SECTION. ╙INCE THERE IS NO SUCH THING AS A PERFECT MECHANICAL
SWITCH, IT IS RECOMMENDED THAT YOU "DEBOUNCE" EACH KEY ROW READ IN THE
FOLLOWING WAY:
AGAIN:
LDA $DC01
CMP $DC01
BNE AGAIN
╙O, TO SCAN THE ENTIRE KEYBOARD, YOU SIMPLY SELECT EACH SCAN ROW IN SOME
ORDER, AND READ AND REMEMBER THE KEYS HELD DOWN ON THE ROW. ┴S IT TURNS OUT,
YOU HAVE TO BE A BIT CAREFUL OF EXACTLY HOW YOU "SELECT" A ROW. ┴LSO, THERE
IS A SHORTCUT THAT YOU CAN TAKE. ╔N ORDER TO FIND OUT IF ANY KEY IS BEING
HELD DOWN IN ONE OPERATION, ALL YOU HAVE TO DO IS SELECT ALL ROWS AT ONCE AND
SEE IF THERE ARE ANY "0" BITS IN THE READ VALUE. ╔F SO, THERE IS A KEY BEING
HELD DOWN SOMEWHERE; IF NOT, THEN THERE IS NO KEY BEING HELD DOWN, SO YOU
DON'T HAVE TO BOTHER SCANNING THE ENTIRE KEYBOARD. ╘HIS WILL REDUCE OUR
KEYSCANNING SIGNIFICANTLY, WHICH IS IMPORTANT, SINCE THE KEYBOARD WILL BE
SCANNED EVERY 1/60 OF A SECOND.
┴S MENTIONED ABOVE, JOYSTICK #1 WILL INTERFERE WITH THE ╦ERNAL READING THE
KEYBOARD. ╘HIS IS BECAUSE THE READ VALUE OF JOYSTICK #1 IS WIRED INTO ├╔┴#1
PORT ┴, THE SAME PLACE THAT THE KEYBOARD READ IS WIRED IN. ╙O, WHENEVER A
SWITCH IN THE JOYSTICK IS PUSHED, THE CORRESPONDING BIT OF THE KEYBOARD SCAN
REGISTER WILL BE FORCED TO "0", REGARDLESS OF WHICH KEYS ARE PRESSED AND
REGARDLESS OF WHICH SCAN ROW IS SELECTED. ╘HERE'S THE CATCH. ╔F WE WERE TO
UN-SELECT ALL SCAN ROWS AND STILL NOTICE "0"S IN THE KEYBOARD READ REGISTER,
THEN WE WOULD KNOW THAT THE JOYSTICK WAS BEING PUSHED AND WOULD INTERFERE WITH
OUR KEYBOARD SCANNING, SO WE COULD ABORT KEYBOARD SCANNING AND HANDLE THIS
CASE AS IF NO KEYS WERE BEING HELD DOWN.
╔T STILL WOULD BE POSSIBLE BUT UNLIKELY THAT THE USER COULD PUSH THE JOYSTICK
IN THE MIDDLE OF US SCANNING THE KEYBOARD AND SCREW UP OUR RESULTS, SO TO
DEFEND AGAINST THIS, WE CHECK FOR THE JOYSTICK BEING PUSHED BOTH BEFORE AND
AFTER SCANNING THE KEYBOARD. ╔F WE FIND THAT THE JOYSTICK IS PUSHED AT EITHER
OF THESE TIMES, THEN WE THROW OUT THE RESULTS AND ASSUME THAT NO KEYS ARE HELD
DOWN. ╘HIS WAY, THE ONLY WAY THAT A USER COULD SCREW UP THE SCANNING IS IF
HE/SHE/IT WERE TO PRESS A SWITCH AFTER WE BEGIN SCANNING AND RELEASE IT BEFORE
WE FINISH SCANNING. ╬OT BLOODY LIKELY FOR A HUMAN.
┘OU GET THE SAME DEAL FOR KEYBOARD SCANNING ON THE 64, EXCEPT YOU ONLY NEED TO
USE $─├00 FOR SELECTING THE SCAN ROWS. ┴LSO NOTE THAT YOU WILL NOT BE ABLE TO
PLAY WITH KEYBOARD SCANNING FROM ┬┴╙╔├ BECAUSE OF THE INTERRUPT READING OF THE
KEYBOARD. ┘OU MUST MAKE SURE THAT INTERRUPTS ARE DISABLED WHEN PLAYING WITH
THE KEYBOARD HARDWARE, OR INTERRUPT SCANNING CAN COME ALONG AT ANY TIME AND
CHANGE ALL OF THE REGISTER SETTINGS.
3.3. ╙├┴╬╬╔╬╟ ╙╧╒╥├┼ ├╧─┼
╘HE FOUR KEYBOARD SCANNING TECHNIQUES OF THE EXAMPLE PROGRAM ARE PRESENTED
BELOW. ╘HE DECLARATIONS REQUIRED FOR ALL OF THEM ARE:
PA = $DC00 ;ROW SELECT
PB = $DC01 ;COLUMN READ
DDRA = $DC02 ;DDR FOR ROW SELECT
DDRB = $DC03 ;DDR FOR COLUMN READ
SCAN╘ABLE .BUF 8 ;STORAGE FOR SCAN
MASK = $03 ;WORK LOCATION
╘HE CODE IS AS FOLLOWS, IN ┬UDDY FORMAT. ┼ACH ROUTINE SCANS THE KEYBOARD AND
STORES THE RESULTS IN THE "SCAN╘ABLE" TABLE.
------------------+------------------+------------------+------------------+
╥OW FORWARD FAST ▄ ╥OW BACKWARD FAST▄ ├OLUMN RIGHT ▄ ╥OW FORWARD SLOW
------------------+------------------+------------------+------------------+
SEI ▄ SEI ▄ SEI ▄ SEI
LDX #0 ▄ LDX #7 ▄ LDA #$00 ▄ LDX #0
LDA #$FE ▄ LDA #$7F ▄ STA DDRA ▄ LDA #$FE
STA PA ▄ STA PA ▄ LDA #$FF ▄ STA MASK
NEXT╥OW = * ▄ NEXT╥OW = * ▄ STA DDRB ▄ NEXT╥OW = *
- LDA PB ▄- LDA PB ▄ LDY #7 ▄ LDA MASK
CMP PB ▄ CMP PB ▄ LDA #$7F ▄ STA PA
BNE - ▄ BNE - ▄ STA MASK ▄- LDA PB
EOR #$FF ▄ EOR #$FF ▄ NEXT├OL = * ▄ CMP PB
STA SCAN╘ABLE,X ▄ STA SCAN╘ABLE,X ▄ LDA MASK ▄ BNE -
SEC ▄ SEC ▄ STA PB ▄ EOR #$FF
ROL PA ▄ ROR PA ▄- LDA PA ▄ STA SCAN╘ABLE,X
INX ▄ DEX ▄ CMP PA ▄ SEC
CPX #8 ▄ BPL NEXT╥OW ▄ BNE - ▄ ROL MASK
BCC NEXT╥OW ▄ CLI ▄ LDX #$FF ▄ INX
CLI ▄ RTS ▄ STX PB ▄ CPX #8
RTS ▄ ▄ EOR #$FF ▄ BCC NEXT╥OW
------------------+------------------+ LDX #7 ▄ CLI
▄- ASL ▄ RTS
╘HE FORWARD "QUICK" SCANNING STORES ▄ ROL SCAN╘ABLE,X +------------------+
THE SCAN ROW SELECTION MASK INTO ▄ DEX ▄
THE ROW SELECTION REGISTER AND ▄ BPL - ▄
SHIFTS THE "0" BIT ONE POSITION ▄ SEC ▄
"FORWARD" FOR EACH ROW, DIRECTLY, ▄ ROR MASK ▄
USING A "ROL $DC00" INSTRUCTION. ▄ DEY ▄
╘HIS WOULD PROBABLY BE THE OBVIOUS ▄ BPL NEXT├OL ▄
SOLUTION TO AN OPTIMIZING ASSEMBLER ▄ LDA #$FF ▄
PROGRAMMER. ╚OWEVER, FOR SOME ▄ STA DDRA ▄
REASON NOT QUITE UNDERSTOOD BY THIS ▄ LDA #$00 ▄
AUTHOR, THERE ARE "SHADOWING" ▄ STA DDRB ▄
PROBLEMS WITH THIS APPROACH. ╔F ▄ CLI ▄
YOU WERE TO HOLD DOWN THE TWO KEYS ▄ RTS ▄
"╚" AND "╦" AT THE SAME TIME, YOU +------------------+
WOULD NOTICE THAT THESE TWO KEYS
ARE ON THE SAME COLUMN OF TWO SUCCESSIVE ROWS. ╔F YOU HOLD THEM BOTH DOWN,
YOU WILL SEE THE TWO POSITIONS BECOME ACTIVE, BUT SO WILL THE SAME COLUMN OF
ALL SUCCESSIVE ROWS AFTER THE "╚" AND "╦", EVEN THOUGH THESE OTHER KEYS ARE
NOT ACTUALLY HELD DOWN. ┘OU WILL GET AN INACCURATE READING IF BAD KEYS ARE
HELD DOWN SIMULTANEOUSLY. ┘OU WILL NOTICE THE USE OF THE TERM "ACTIVE" ABOVE.
╘HIS IS BECAUSE ALTHOUGH THE HARDWARE RETURNS A "0" FOR ACTIVE, THE ROUTINE
CONVERTS THAT INTO A "1" FOR EASIER PROCESSING LATER. ╔ AM NOT SURE IF
EVERYONE WILL GET THIS SAME RESULT, BUT IF YOUR KEYBOARD IS WIRED THE SAME AS
MINE, YOU WILL.
╘HE BACKWARD "QUICK" SCANNING OPERATES QUITE SIMILARLY TO THE FORWARD
SCANNING, EXCEPT FOR THE DIRECTION OF THE SCAN AND THE DIRECTION OF THE
"SHADOW"; THE SHADOW GOES UPWARDS. ┘OU MIGHT THINK THAT ┴╬─ING TOGETHER THE
RESULTS OF THE FORWARD AND BACKWARD SCAN TOGETHER WOULD ELIMINATE THE SHADOW,
BUT THIS WILL NOT WORK SINCE ANY ROWS BETWEEN THE ROWS CONTAINING THE TWO KEYS
HELD DOWN WILL BE INCORRECTLY READ AS BEING ACTIVE.
╘HE COLUMNWISE RIGHT SCANNING IS THE MOST COMPLICATED BECAUSE THE ROWS MUST BE
CONVERTED INTO COLUMNS, TO ALLOW THE SCAN MATRIX TO BE INTERPRETED AS BEFORE.
┴LSO, THE ─ATA ─IRECTION ╥EGISTERS HAVE TO BE CHANGED. ┘OU MIGHT THINK THAT
COMBINGING ROW-WISE SCANNING WITH COLUMNWISE SCANNING WOULD GIVE BETTER
RESULTS, AND IT PROBABLY WOULD, IF IT WEREN'T FOR A BIZARRE HARDWARE PROBLEM.
╔F YOU HOLD DOWN TWO OR MORE KEYS ON THE SAME SCAN ROW, SAY "╫" AND "┼", SOME
OF THE KEYS WILL FLICKER OR DISAPPEAR, GIVING AN INACCURATE READING.
╘HE FORWARD "SLOW" SCANNING IS THE BEST OF THE BUNCH. ╔NCIDENTALLY, IT IS
WHAT THE ╦ERNAL USES (AS NEAR AS ╔ CAN FIGURE - THEIR CODE IS EXTREMELY
CONVOLUTED). ╘HIS TECHNIQUE IS THE SAME AS THE FORWARD "QUICK SCAN," EXCEPT
THAT THE ROW SELECTION MASK IS SHIFTED IN A WORKING STORAGE LOCATION AND POKED
INTO THE ├╔┴ REGISTER, RATHER THAN BEING SHIFTED IN PLACE. ╔ DON'T KNOW WHY
THIS MAKES A DIFFERENCE, BUT IT DOES. ╘HERE IS STILL A PROBLEM WITH THIS
TECHNIQUE, BUT THIS PROBLEM OCCURS WITH ALL TECHNIQUES. ╔F YOU HOLD DOWN
THREE KEYS THAT FORM THREE "CORNERS" OF A RECTANGLE IN THE SCANNING MATRIX,
THEN THE MISSING CORNER WILL BE READ AS BEING HELD DOWN ALSO. ╞OR EXAMPLE, IF
YOU HOLD DOWN "├", "╬", AND "═", THEN THE KEYBOARD HARDWARE WILL ALSO THINK
THAT YOU ARE HOLDING DOWN THE "╪" KEY. ╘HIS IS WHY THIS ARTICLE IMPLEMENTS A
"THREE-KEY" ROLLOVER RATHER THAN AN "╬-KEY" ROLLOVER. ═ANY THREE-KEY
COMBINATIONS WILL STILL BE INTERPRETED CORRECTLY. ╬OTE, HOWEVER, THAT SHIFT
KEYS SUCH AS ╙╚╔╞╘ OR ├╧╬╘╥╧╠ WILL ADD ONE MORE KEY TO THE HARDWARE SCANNING
(BUT WILL NOT BE COUNTED IN THE THREE-KEY ROLLOVER), MAKING INACCURATE RESULTS
MORE LIKELY IF YOU ARE HOLDING DOWN MULTIPLE OTHER KEYS AT THE SAME TIME.
4. ╘╚┼ ├-128 ╦┼┘╙├┴╬╬┼╥
╘HIS SECTION GIVES THE SOURCE CODE FOR THE ├-128 IMPLEMENTATION OF THE
THREE-KEY ROLLOVER. ╘HE FORWARD "SLOW" KEY MATRIX SCANNING TECHNIQUE IS USED,
EXTENDED TO WORK WITH THE EXTRA KEYS OF THE 128. ╔T WAS A BIT OF A PAIN
WEDGING INTO THE ╦ERNAL, SINCE THERE IS NOT A CONVENIENT INDIRECT ╩═╨ INTO
SCANNING THE KEYBOARD, LIKE THERE ARE FOR DECODING AND BUFFERING PRESSED KEYS.
┴ RATHER LENGTHY ╔╥╤ "PREAMBLE" HAD TO BE COPIED FROM THE ╥╧═, UP TO THE
POINT WHERE IT ╩╙╥S TO THE KEYSCANNING ROUTINE. ╘HIS CODE IN INCLUDED IN
THE FORM OF A ".BYTE" TABLE, TO SPARE YOU THE DETAILS.
┬EFORE SCANNING THE KEYBOARD, WE CHECK TO SEE IF JOYSTICK #1 IS PUSHED AND IF
A KEY IS ACTUALLY PRESSED. ╔F NOT, WE ABORT SCANNING AND ╩═╨ TO THE KEY
REPEAT HANDLING IN THE ╥╧═. ╔F A KEY IS HELD DOWN, WE SCAN THE KEYBOARD AND
THEN EXAMINE THE RESULT. ╞IRST WE CHECK FOR THE SHIFT KEYS (╙╚╔╞╘, ├╧══╧─╧╥┼,
├╧╬╘╥╧╠, ┴╠╘, AND ├┴╨╙ ╠╧├╦), PUT THEM INTO LOCATION $─3 (SHIFT FLAGS) IN BIT
POSTITIONS 1, 2, 4, 8, AND 16, RESPECTIVELY, AND REMOVE THEM FROM THE SCAN
MATRIX. ╘HE ├┴╨╙ ╠╧├╦ KEY IS NOT ON THE MAIN KEY MATRIX; IT IS READ FROM THE
PROCESSOR ╔/╧ PORT. ╘HIS IS GOOD, BECAUSE OTHERWISE WE COULD NOT ABORT
SCANNING IF IT WERE THE ONLY KEY HELD DOWN.
╘HEN WE SCAN THE KEYMATRIX FOR THE FIRST THREE KEYS THAT ARE BEING HELD DOWN,
OR AS MANY AS ARE HELD DOWN IF LESS THAN THREE. ╫E STORE THE SCAN CODES OF
THESE KEYS INTO A 3-ELEMENT ARRAY. ╫E ALSO RETAIN A COPY OF THE 3-ELEMENT
ARRAY FROM THE PREVIOUS SCAN AND WE CHECK FOR DIFFERENT KEYS BEING IN THE TWO
ARRAYS. ╔F THE OLD ARRAY CONTAINS A KEY THAT IS NOT PRESENT IN THE NEW ARRAY,
THEN THE USE HAS RELEASED A KEY, SO WE SET A FLAG TO INHIBIT INTERPRETATION OF
KEYS AND PRETEND THAT NO KEYS ARE HELD DOWN. ╘HIS IS TO ELIMINATE UNDESIRABLE
EFFECTS OF HAVING OTHER KEYS HELD DOWN REPEAT IF YOU RELEASE THE MOST RECENTLY
PUSHED KEY FIRST. ╨├ KEYBOARDS DO THIS. ╘HIS INHIBITING WILL BE IGNORED IF
NEW KEYS ARE DISCOVERED IN THE NEXT STEP.
╔F THERE ARE KEYS IN THE NEW ARRAY THAT ARE NOT IN THE OLD, THEN THE USER HAS
JUST PRESSED A NEW KEY, SO THAT NEW KEY GOES TO THE HEAD OF THE OLD ARRAY AND
WE STOP COMPARING THE ARRAYS THERE. ╘HE KEY IN THE FIRST POSITION OF THE OLD
ARRAY IS POKED INTO THE ╦ERNAL "KEY HELD DOWN" LOCATION FOR THE ╦ERNAL TO
INTERPRET LATER. ╔F MORE THAN ONE NEW KEY IS DISCOVERED AT THE SAME TIME,
THEN EACH OF THE NEW KEYS WILL BE PICKED UP ON SUCCESSIVE KEYBOARD SCANS AND
WILL BE INTERPRETED AS JUST BEING PUSHED. ╙O, IF YOU PRESS THE "┴", "╬", AND
"─" KEYS ALL AT THE SAME TIME, SOME PERMUTATION OF ALL THREE OF THESE KEYS
WILL APPEAR ON THE SCREEN.
╫HEN WE ARE DONE INTERPRETING THE KEYS, WE CHECK THE JOYSTICK ONCE MORE AND IF
IT IS STILL INACTIVE, WE PRESENT THE MOST RECENTLY PUSHED DOWN KEY TO THE
╦ERNAL AND ╩═╨ INTO THE ╥╧═ KEYBOARD DECODING ROUTINE.
╒NLIKE IN PREVIOUS ISSUES, THIS SOURCE CODE IS HERE IN LITERAL FORM; JUST
EXTRACT EVERYTHING BETWEEN THE "-----=-----"S TO NAB THE SOURCE FOR YOURSELF.
╘HE SOURCE IS IN ┬UDDY ASSEMBLER FORMAT.
-----=-----
;3-╦EY ╥OLLOVER-128 BY ├RAIG ┬RUCE 18-╩UN-93 FOR ├= ╚ACKING MAGAZINE
.ORG $1500
.OBJ "@0:KEYSCAN128"
SCANROWS = 11
ROLLOVER = 3
PA = $DC00
PB = $DC01
PK = $D02F
JMP INITIAL╔NSTALL
;UGLY ╔╥╤ PATCH CODE.
IRQ = * ;$1503
.BYTE $D8,$20,$0A,$15,$4C,$69,$FA,$38,$AD,$19,$D0,$29,$01,$F0,$07,$8D
.BYTE $19,$D0,$A5,$D8,$C9,$FF,$F0,$6F,$2C,$11,$D0,$30,$04,$29,$40,$D0
.BYTE $31,$38,$A5,$D8,$F0,$2C,$24,$D8,$50,$06,$AD,$34,$0A,$8D,$12,$D0
.BYTE $A5,$01,$29,$FD,$09,$04,$48,$AD,$2D,$0A,$48,$AD,$11,$D0,$29,$7F
.BYTE $09,$20,$A8,$AD,$16,$D0,$24,$D8,$30,$03,$29,$EF,$2C,$09,$10,$AA
.BYTE $D0,$28,$A9,$FF,$8D,$12,$D0,$A5,$01,$09,$02,$29,$FB,$05,$D9,$48
.BYTE $AD,$2C,$0A,$48,$AD,$11,$D0,$29,$5F,$A8,$AD,$16,$D0,$29,$EF,$AA
.BYTE $B0,$08,$A2,$07,$CA,$D0,$FD,$EA,$EA,$AA,$68,$8D,$18,$D0,$68,$85
.BYTE $01,$8C,$11,$D0,$8E,$16,$D0,$B0,$13,$AD,$30,$D0,$29,$01,$F0,$0C
.BYTE $A5,$D8,$29,$40,$F0,$06,$AD,$11,$D0,$10,$01,$38,$58,$90,$07,$20
.BYTE $AA,$15,$20,$E7,$C6,$38,$60
;KEYSCANNING ENTRY POINT
MAIN = *
LDA #0 ;CHECK IF ANY KEYS ARE HELD DOWN
STA PA
STA PK
- LDA PB
CMP PB
BNE -
CMP #$FF
BEQ NO╦EY╨RESSED ;IF NOT, THEN DON'T SCAN KEYBOARD, GOTO ╦ERNAL
JSR CHECK╩OYSTICK ;IF SO, MAKE SURE JOYSTICK NOT PRESSED
BCC JOYSTICK╨RESSED
JSR KEYSCAN ;SCAN THE KEYBOARD AND STORE RESULTS
JSR CHECK╩OYSTICK ;MAKE SURE JOYSTICK NOT PRESSED AGAIN
BCC JOYSTICK╨RESSED
JSR SHIFTDECODE ;DECODE THE SHIFT KEYS
JSR KEYDECODE ;DECODE THE FIRST 3 REGULAR KEYS HELD DOWN
JSR KEYORDER ;SEE WHICH NEW KEYS PRESSED, OLD KEYS RELEASED, AND
; DETERMINE WHICH KEY TO PRESENT TO THE ╦ERNAL
LDA $033E ;SET UP FOR AND DISPATCH TO ╦ERNAL
STA $CC
LDA $033F
STA $CD
LDX #$FF
BIT IGNORE╦EYS
BMI ++
LDA PREV╦EYS+0
CMP #$FF
BNE +
LDA $D3
BEQ ++
LDA #88
+ STA $D4
TAY
JMP ($033A)
NO╦EY╨RESSED = * ;NO KEYS PRESSED; SELECT DEFAULT SCAN ROW
LDA #$7F
STA PA
LDA #$FF
STA PK
JOYSTICK╨RESSED = *
LDA #$FF ;RECORD THAT NO KEYS ARE DOWN IN OLD 3-KEY ARRAY
LDX #ROLLOVER-1
- STA PREV╦EYS,X
DEX
BPL -
JSR SCAN├APS ;SCAN THE ├┴╨╙ ╠╧├╦ KEY
LDX #$FF
LDA #0
STA IGNORE╦EYS
+ LDA #88 ;PRESENT "NO KEY HELD" TO ╦ERNAL
STA $D4
TAY
JMP $C697
INITIAL╔NSTALL = * ;INSTALL WEDGE: SET RESTORE VECTOR, PRINT MESSAGE
JSR INSTALL
LDA #<REINSTALL
LDY #>REINSTALL
STA $0A00
STY $0A01
LDX #0
- LDA INSTALL═SG,X
BEQ +
JSR $FFD2
INX
BNE -
+ RTS
INSTALL═SG = *
.BYTE 13
.ASC "KEYSCAN128 INSTALLED"
.BYTE 0
REINSTALL = * ;RE-INSTALL WEDGE AFTER A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼
JSR INSTALL
JMP $4003
INSTALL = * ;GUTS OF INSTALLATION: SET ╔╥╤ VECTOR TO PATCH CODE
SEI ; AND INITIALIZE SCANNING VARIABLES
LDA #<IRQ
LDY #>IRQ
STA $0314
STY $0315
CLI
LDX #ROLLOVER-1
LDA #$FF
- STA PREV╦EYS,X
DEX
BPL -
LDA #0
STA IGNORE╦EYS
RTS
MASK = $CC
KEYSCAN = * ;SCAN THE (EXTENDED) KEYBOARD USING THE FORWARD
LDX #$FF ; ROW-WISE "SLOW" TECHNIQUE
LDY #$FF
LDA #$FE
STA MASK+0
LDA #$FF
STA MASK+1
JMP +
NEXT╥OW = *
- LDA PB
CMP PB
BNE -
STY PA
STY PK
EOR #$FF
STA SCAN╘ABLE,X
SEC
ROL MASK+0
ROL MASK+1
+ LDA MASK+0
STA PA
LDA MASK+1
STA PK
INX
CPX #SCANROWS
BCC NEXT╥OW
RTS
SHIFT╓ALUE = $D3
SHIFT╥OWS .BYTE $01,$06,$07,$07,$0A
SHIFT┬ITS .BYTE $80,$10,$20,$04,$01
SHIFT═ASK .BYTE $01,$01,$02,$04,$08
SHIFTDECODE = * ;SEE WHICH "SHIFT" KEYS ARE HELD DOWN, PUT THEM INTO
JSR SCAN├APS ; PROPER POSITIONS IN $─3 (SHIFT FLAGS), AND REMOVE
LDY #4 ; THEM FROM THE SCAN MATRIX
- LDX SHIFT╥OWS,Y
LDA SCAN╘ABLE,X
AND SHIFT┬ITS,Y
BEQ +
LDA SHIFT═ASK,Y
ORA SHIFT╓ALUE
STA SHIFT╓ALUE
LDA SHIFT┬ITS,Y
EOR #$FF
AND SCAN╘ABLE,X
STA SCAN╘ABLE,X
+ DEY
BPL -
RTS
SCAN├APS = * ;SCAN THE ├┴╨╙ ╠╧├╦ KEY FROM THE PROCESSOR ╔/╧ PORT
- LDA $1
CMP $1
BNE -
EOR #$FF
AND #$40
LSR
LSR
STA SHIFT╓ALUE
RTS
NEWPOS = $CC
KEYCODE = $D4
XSAVE = $CD
KEYDECODE = * ;GET THE SCAN CODES OF THE FIRST THREE KEYS HELD DOWN
LDX #ROLLOVER-1 ;INITIALIZE: $FF MEANS NO KEY HELD
LDA #$FF
- STA NEW╦EYS,X
DEX
BPL -
LDY #0
STY NEWPOS
LDX #0
STX KEYCODE
DECODE╬EXT╥OW = * ;DECODE A ROW, INCREMENTING THE CURRENT SCAN CODE
LDA SCAN╘ABLE,X
BEQ DECODE├ONTINUE
;AT THIS POINT, WE KNOW THAT THE ROW HAS A KEY HELD
LDY KEYCODE
- LSR
BCC ++
PHA ;HERE WE KNOW WHICH KEY IT IS, SO STORE ITS SCAN CODE,
STX XSAVE ; UP TO 3 KEYS
LDX NEWPOS
CPX #ROLLOVER
BCS +
TYA
STA NEW╦EYS,X
INC NEWPOS
+ LDX XSAVE
PLA
+ INY
CMP #$00
BNE -
DECODE├ONTINUE = *
CLC
LDA KEYCODE
ADC #8
STA KEYCODE
INX
CPX #SCANROWS
BCC DECODE╬EXT╥OW
RTS
;KEYORDER: DETERMINE WHAT KEY TO PRESENT TO THE ╦ERNAL AS BEING LOGICALLY THE
;ONLY ONE PRESSED, BASED ON WHICH KEYS PREVIOUSLY HELD HAVE BEEN RELEASED AND
;WHICH NEW KEYS HAVE JUST BEEN PRESSED
KEYORDER = *
;** REMOVE OLD KEYS NO LONGER HELD FROM OLD SCAN CODE ARRAY
LDY #0
NEXT╥EMOVE = *
LDA PREV╦EYS,Y ;GET CURRENT OLD KEY
CMP #$FF
BEQ ++
LDX #ROLLOVER-1 ;SEARCH FOR IT IN THE NEW SCAN CODE ARRAY
- CMP NEW╦EYS,X
BEQ +
DEX
BPL -
TYA ;HERE, OLD KEY NO LONGER HELD; REMOVE IT
TAX
- LDA PREV╦EYS+1,X
STA PREV╦EYS+0,X
INX
CPX #ROLLOVER-1
BCC -
LDA #$FF
STA PREV╦EYS+ROLLOVER-1
STA IGNORE╦EYS
+ INY ;CHECK NEXT OLD KEY
CPY #ROLLOVER
BCC NEXT╥EMOVE
;** INSERT NEW KEYS AT FRONT OF OLD SCAN CODE ARRAY
+ LDY #0
NEXT╔NSERT = *
LDA NEW╦EYS,Y ;GET CURRENT NEW KEY
CMP #$FF
BEQ ++
LDX #ROLLOVER-1 ;CHECK OLD SCAN CODE ARRAY FOR IT
- CMP PREV╦EYS,X
BEQ +
DEX
BPL -
PHA ;IT'S NOT THERE, SO INSERT NEW KEY AT FRONT, EXIT
LDX #ROLLOVER-2
- LDA PREV╦EYS+0,X
STA PREV╦EYS+1,X
DEX
BPL -
LDA #0
STA IGNORE╦EYS
PLA
STA PREV╦EYS+0
LDY #ROLLOVER ;(TRICK TO EXIT)
+ INY
CPY #ROLLOVER
BCC NEXT╔NSERT
+ RTS ;NOW, THE HEAD OF THE OLD SCAN CODE ARRAY CONTAINS
; THE SCAN CODE TO PRESENT TO THE ╦ERNAL, AND OTHER
; POSITIONS REPRESENT KEYS THAT ARE ALSO HELD DOWN
; THAT HAVE ALREADY BEEN PROCESSED AND THEREFORE CAN
; BE IGNORED UNTIL THEY ARE RELEASED
CHECK╩OYSTICK = * ;CHECK IF JOYSTICK IS PUSHED: UN-SELECT ALL KEYBOARD
LDA #$FF ; ROWS AND SEE IF THERE ARE ANY "0"S IN THE SCAN
STA PA ; STATUS REGISTER
STA PK
- LDA PB
CMP PB
BNE -
CMP #$FF
LDA #$7F ;RESTORE TO DEFAULT ╦ERNAL ROW SELECTED (TO THE ONE
STA PA ; CONTAINING THE ╙╘╧╨ KEY)
LDA #$FF
STA PK
RTS
;GLOBAL VARIABLES
SCAN╘ABLE .BUF SCANROWS ;VALUES OF THE ELEVEN KEYBOARD SCAN ROWS
NEW╦EYS .BUF ROLLOVER ;CODES OF UP TO THREE KEYS HELD SIMULTANEOUSLY
IGNORE╦EYS .BUF 1 ;FLAG: IF AN OLD KEY HAS BEEN RELEASED AND NO
; NEW KEY HAS BEEN PRESSED, STOP ALL KEY
; REPEATING
PREV╦EYS .BUF ROLLOVER+2 ;KEYS HELD ON PREVIOUS SCAN
-----=-----
┴ND THAT'S ALL THERE IS TO IT. :-)
5. ╘╚┼ ├-64 ╦┼┘╙├┴╬╬┼╥
╘HE BOOT PROGRAM FOR THE ├-64 KEYSCANNER IS AS FOLLOWS:
10 D=PEEK(186)
20 IF A=1 THEN 60
30 A=1
40 LOAD"KEYSCAN64",D,1
50 GOTO 10
60 SYS 49152+5*256 : REM $C500
╔T IS VERY MUCH LIKE BOOT PROGRAMS FOR OTHER MACHINE LANGUAGE PROGRAMS THAT
DON'T LOAD AT THE START OF ┬┴╙╔├. ╔T WILL LOAD THE BINARY FROM THE LAST
DEVICE ACCESSED, AND ACTIVATE IT.
┴ LISTING OF THE ├-64 KEYSCANNING CODE IS NOT PRESENTED HERE BECAUSE IT IS SO
SIMILAR TO THE ├-128 LISTING. ╘HE ONLY THINGS THAT ARE DIFFERENT ARE THE
╦ERNAL PATCHES AND THE KEYBOARD SCANNING (BECAUSE THE THREE EXTRA ROWS DON'T
HAVE TO BE SCANNED). ╘HE ╔╥╤ HAD TO BE SUBSTANTIALLY COPIED FROM THE ╥╧═,
AGAIN, TO GET AT THE CALL TO THE KEY SCANNING. ┴LSO, RATHER THAN TAKING
OVER THE ┬┴╙╔├ RESET VECTOR (SINCE THERE ISN'T ONE), THE ╬═╔ VECTOR IS
TAKEN OVER TO INSURE THE SURVIVAL OF THE KEY SCANNER AFTER A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼.
┴ BIT OF ITS PREAMBLE ALSO HAD TO BE COPIED OUT OF ╥╧═ TO GET AT THE GOOD
STUFF. ╔F YOU WANT A COPY OF THE ├-64 LISTING, YOU CAN E-MAIL ME.
6. ╒╒┼╬├╧─┼─ ╞╔╠┼╙
╚ERE ARE THE BINARY EXECUTABLES IN UUENCODED FORM. ╘HE ├╥├32S OF THE FOUR
FILES ARE AS FOLLOWS:
CRC32 = 3398956287 FOR "KEYSCAN128"
CRC32 = 2301926894 FOR "KEYSCAN64.BOOT"
CRC32 = 1767081474 FOR "KEYSCAN64"
CRC32 = 1604419896 FOR "KEYSHOW"
BEGIN 640 KEYSCAN128
═└!5,'┴;8(└╚53&╟┌.*╘9╘"─!\└>-&="┼╓,╟_\&\╠$=└╨!"┼└╘#$╪╔=├╨+"38
═4└:═-└╩-$═"┼└2╟]"01(╦2╘*2*╘1╘"┼_"2"╚╦1;0)-@╨└╥╟╧+└─0╩═└╚╩?^-
═$═"┼└0─"*?╠%╓4┬═+└╔(╦1'0*5^╚╦1;0*>^╩╠└┬┬!\╦0_>╦╩╩╞┬-&-!╚┴0&,
═$=".%═"╨$┌╘╨╘"─!\└╥┼╓"┼└\└:═$=└0└3┴8─└<@╩┴4@┘\8╪8*─└├0#<├2_0
═╦0'<╙0'<╘/├)__└┌((─7─#\@<18@┬1>0-╥"╫%┬#╠%┬└╠%┌╘^└╪7,╦3\#┴<╓┬
═_╥╥╘%╙└╤╦;47╥?_0!╩73\":╔6(74╩&╨┌└┌┼_├0#<╩?^-+]"╔_┌("╟;47╥┴#┌
═(-╘6╚╧^╔└(╓╘%┌┼8┴=2╚3)?&(%46╩4^@%╚╘└"╚╨!"╩(└╧3─6\└8@╘╧_╚╘/5@
═#4═%65-#04╪╤,├@@24┘35$%,3$5$└"!5%─╨#0'┬╔└┌└5├10#├!4#6*("╩?^=
══1?*$/╩╔└(╓╘%╓"┬_┌#_╩?┌%╙*╟_┴<╒,╞!:═└=╙-└=╙0^(╨└╫(╨╧╘$╟_╟:87
═.";,)╠╓┼╙(╘└╫*7-├2_0┌.└+─-┼@└08'!╨╩└$"└$└0$!└@0((-╘6╚└2^╩!:]
═╔┴<┘╦1;╨$╦╞╥%@73┴=.┘╦19)_╙╓╞%┘╓╞%╪@0╪&"┼└<4!╘/╔)_╥┼└2─╩%╘╓"┬
═└╩╟_╟;$7╥┴#┌╚└"$╙*(└┴═2]╔┴?╨'*342╔└22(;-╔╠╙@└[└&╞)╓╤%^;,╔╠╒╚
═╥,─└╘.88╔=1╔"(74┌.└+─--@╚└"┘═1?)__└─╚@+=╠1?╨&,╚0^)┬╩╧;87╟;47
═┌.└"─/6╔_╪╓╫%╪╓╘%\├└└┘#5╚└"┘╠1?)__└╞╚@+=═1?╨&╠╚0^$┬┬└;╓╒%┘╓╓
═%\╚0]┌─└├;07:(╓╒%┌└#╥,└#─--@╩?^-└-╥-+]"═└=╙-└=╙0^,╟_╩7^-└-╥╔
9_╪╘╧╘&└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└
└
END
BEGIN 640 KEYSCAN64.BOOT
═└0@."└╚└1++"*#$╪-┬─└'0@4└(╠@0;(╤(*<@-├└└)0@>└$&╥,0└┌""@└─╥)+
═15┼30╘%.-├0┬+$0╠,0!#"#(└┬2└╤,└!@"#╨└╟┬└╘.3$╒,╩╚╒╦#(╒-┬└@.┬"/
)("1#-3└╨└└└└└└└└
└
END
BEGIN 640 KEYSCAN64
═└,5,╤,5,$,9,┌╠4@┌╧^┼╙-└╔╤╠╫0):─4┴<╓─╘╘;/╦╚<"╠=&╨$>;/┴<╪@).╩╤
═\╪╓'└╩┌&└╩7.28└@'.╩┼└2─0\└╩@└(3└╔0$)(-└(╔<#0!╩4!*1^%└2!9╤4╤^
═┌╩─└├0#<╦0'<╙0'<╘/├)__└┘(%├'─#─@6,8@6,>0,2"-╤┬"[╤┬#[╤╩╞!┴?6╔
═┌╪7╓╚╧\╠>,<╨+:╒┘╤\╟_╘└>═├0+╨(:┼└┴<╬╚;(\"╩7^-└-╥╔_┌("╟7╟'╥┴#┌
═(+7&╚╧^╔└(╒╪╤┌┼└┴<╬╚3";╦(.╦%╚@"]╒<7╨!┬#2_^├0]6!+15┼30╘%.-├0@
═24┘35$%,3$5$#0!╪╩0╞@╤8╘4└╪╨5└┌─╟╚,:-&└.,&0-8╚@*╔_┘╒┘╤\╚0^╩─└
═├7├'8'┬╔,:#╩├10#├!4#╩4>@_╚╘8└╪╨9└╒┴@2(╔(╞$┬╔?╪╘-╫:╨-╫3└?(└+]
═╘└-╠└╚└@╧/8@╪?_0#╥└5_2"├_2└8┘2#╩╤6╨"╚$╤╥_╩+_╚/^╔_╚7╒3';&╦0'<
═╙0'<╘/┬,└-╤)_┘╒═╤╙@╞]:7╒├0#<┌.└(─.-@└08'!╪└0(└0!└0($(+7&╚└.^
═@<:];<<┘┴<;╨%+╞)╤@╓-└╚╓-└╦╞%╤─╟_/6╫'╟6╫'┬!#>8*─└├8╘"8*("╩?^=
═=<?*$/╩@└(3╒╚@"&╥[╒═╤_└<╔,═*─!)(┴╧:╞]>└#╠└:8╟77'┘╧6╞]╞├(╥0#0
═┘┴┬┼╥╓─(┴<╧╚╪└┬0╘╓"@└+┼┘╤\╟_\"2┬└═╒╒╤_└8╥┴#╪╞*╩]>╠>=><?╚╪└*0
═]:╟_├7╧'├7├'╥,└#─-6@└+┼╒╤\╟_\":┬└═╒┘╤_└:╥┴#╪2*(!╧7╟'╟7╦'╥┴#╫
═╩0"->,=╚├7╟'╚└/(╨└.0╘╓"╔_╪╘└╫*╘!╫,╘!╫-#╪╥?^╔?╪╘└╫&└└└└└└└└└└
*└└└└└└└└└└└└└└└└
└
END
BEGIN 640 KEYSHOW
═└!-,"╤,└└└└└└└└└└*╞3(-+_(#83╚@└@%╤0@5┴.┬"┬└7%"!╘$┌(4(!<4(/03
═╚┴╪@%╤0@3!1,$!-╪╚@"╔_╚╘└╫*╘!╫,╘!╫-#╪2?^=└╤,╪+@#<┌.└(─.╔88'┬┬
═!┌┼_├0#<╦0'<╙0'<╘/┴)_┘╘#$╙┴╬└-╙*$.╤88'┬╔└(╘"╫*╟_├0/<╚└>╔?╪4#
═╔0.-└=╥═└-╙-└-╙0^*+_├@'<2?^┬!╨╚^└╤/*$/─╪9@.($-╓╔_╪╘"╫*─└├0/<
═6&!╪╩0"-└═╥╔_╪╘#╫*└'╩7^%└┌4#├0'<╦0#<╙0#<╘/┬┬_╪╪!╫$╟_╚@<*/@,3
═╥┴#┘.&8#┬!#=╩?^-└═╥╔└(╘#╫%┴@>*(└╩?┌%└┌4#├0#<╦0'<╙0'<╘/┴)_┘╘#
═$╙@╞└^├@")#╞6&"@!(8$┴└6┬└+╘#$╥└╓%!┬┼!&─╚┴020└╬8%┌.└(─.╔@┴0*@
6!╘8"╩0!╔,)$$┬!#╒8└└└└└└└└*(└8└└└
└
END
================================================================================
╔N THE ╬EXT ╔SSUE:
╬EXT ╔SSUE:
╘ECH-TECH - MORE RESOLUTION TO VERTICAL SHIFT
╧NE TIME HALF OF THE DEMOS HAD PICTURES WAVING HORIZONTALLY ON THE WIDTH
OF THE WHOLE SCREEN. ╘HIS EFFECT IS NAMED TECH-TECH AND IT IS DONE USING
CHARACTER GRAPHICS. ╚OW EXACTLY AND IS THE SAME POSSIBLE WITH SPRITES ?
╘╚┼ ─┼╙╔╟╬ ╧╞ ┴├┼-128/64
─ESIGN OF ┴├┼-128/64 COMMAND SHELL ENVIRONMENT (AND KERNEL REPLACEMENT). ╘HIS
WILL COVER THE ORGANIZATION, INTERNAL OPERATION, AND THE KERNEL INTERFACE OF
THE STILL-UNDER-DEVELOPMENT BUT POSSIBLY CATCHING-ON KERNEL REPLACEMENT FOR
THE 128 AND 64. ╘HE ARTICLE WILL ALSO DISCUSS FUTURE DIRECTIONS AND DESIGNS
FOR THE ┴├┼ ENVIRONMENT. ┴├┼ HAS A NUMBER OF DEFINITE DESIGN ADVANTAGES OVER
OTHER KERNEL REPLACEMENTS, AND A FEW DISADVANTAGES AS WELL.